You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-07-29 22:01:14 +03:00
data-model: simplify users and sessions
This commit is contained in:
@ -136,7 +136,7 @@ pub async fn lookup_active_compat_access_token(
|
||||
res.user_email_confirmed_at,
|
||||
) {
|
||||
(Some(id), Some(email), Some(created_at), confirmed_at) => Some(UserEmail {
|
||||
data: id.into(),
|
||||
id: id.into(),
|
||||
email,
|
||||
created_at,
|
||||
confirmed_at,
|
||||
@ -147,7 +147,7 @@ pub async fn lookup_active_compat_access_token(
|
||||
|
||||
let id = Ulid::from(res.user_id);
|
||||
let user = User {
|
||||
data: id,
|
||||
id,
|
||||
username: res.user_username,
|
||||
sub: id.to_string(),
|
||||
primary_email,
|
||||
@ -274,7 +274,7 @@ pub async fn lookup_active_compat_refresh_token(
|
||||
res.user_email_confirmed_at,
|
||||
) {
|
||||
(Some(id), Some(email), Some(created_at), confirmed_at) => Some(UserEmail {
|
||||
data: id.into(),
|
||||
id: id.into(),
|
||||
email,
|
||||
created_at,
|
||||
confirmed_at,
|
||||
@ -285,7 +285,7 @@ pub async fn lookup_active_compat_refresh_token(
|
||||
|
||||
let id = Ulid::from(res.user_id);
|
||||
let user = User {
|
||||
data: id,
|
||||
id,
|
||||
username: res.user_username,
|
||||
sub: id.to_string(),
|
||||
primary_email,
|
||||
@ -326,7 +326,7 @@ pub async fn compat_login(
|
||||
|
||||
// First, lookup the user
|
||||
let user = lookup_user_by_username(&mut txn, username).await?;
|
||||
tracing::Span::current().record("user.id", tracing::field::display(user.data));
|
||||
tracing::Span::current().record("user.id", tracing::field::display(user.id));
|
||||
|
||||
// Now, fetch the hashed password from the user associated with that session
|
||||
let hashed_password: String = sqlx::query_scalar!(
|
||||
@ -337,7 +337,7 @@ pub async fn compat_login(
|
||||
ORDER BY up.created_at DESC
|
||||
LIMIT 1
|
||||
"#,
|
||||
Uuid::from(user.data),
|
||||
Uuid::from(user.id),
|
||||
)
|
||||
.fetch_one(&mut txn)
|
||||
.instrument(tracing::info_span!("Lookup hashed password"))
|
||||
@ -365,7 +365,7 @@ pub async fn compat_login(
|
||||
VALUES ($1, $2, $3, $4)
|
||||
"#,
|
||||
Uuid::from(id),
|
||||
Uuid::from(user.data),
|
||||
Uuid::from(user.id),
|
||||
device.as_str(),
|
||||
created_at,
|
||||
)
|
||||
@ -392,7 +392,7 @@ pub async fn compat_login(
|
||||
compat_session.id = %session.data,
|
||||
compat_session.device.id = session.device.as_str(),
|
||||
compat_access_token.id,
|
||||
user.id = %session.user.data,
|
||||
user.id = %session.user.id,
|
||||
),
|
||||
err(Display),
|
||||
)]
|
||||
@ -477,7 +477,7 @@ pub async fn expire_compat_access_token(
|
||||
compat_session.device.id = session.device.as_str(),
|
||||
compat_access_token.id = %access_token.data,
|
||||
compat_refresh_token.id,
|
||||
user.id = %session.user.data,
|
||||
user.id = %session.user.id,
|
||||
),
|
||||
err(Display),
|
||||
)]
|
||||
@ -668,7 +668,7 @@ impl TryFrom<CompatSsoLoginLookup> for CompatSsoLogin<PostgresqlBackend> {
|
||||
res.user_email_confirmed_at,
|
||||
) {
|
||||
(Some(id), Some(email), Some(created_at), confirmed_at) => Some(UserEmail {
|
||||
data: id.into(),
|
||||
id: id.into(),
|
||||
email,
|
||||
created_at,
|
||||
confirmed_at,
|
||||
@ -681,7 +681,7 @@ impl TryFrom<CompatSsoLoginLookup> for CompatSsoLogin<PostgresqlBackend> {
|
||||
(Some(id), Some(username), primary_email) => {
|
||||
let id = Ulid::from(id);
|
||||
Some(User {
|
||||
data: id,
|
||||
id,
|
||||
username,
|
||||
sub: id.to_string(),
|
||||
primary_email,
|
||||
@ -808,14 +808,14 @@ pub async fn get_compat_sso_login_by_id(
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
user.id = %user.data,
|
||||
user.username = user.username,
|
||||
%user.id,
|
||||
%user.username,
|
||||
),
|
||||
err(Display),
|
||||
)]
|
||||
pub async fn get_paginated_user_compat_sso_logins(
|
||||
executor: impl PgExecutor<'_>,
|
||||
user: &User<PostgresqlBackend>,
|
||||
user: &User,
|
||||
before: Option<Ulid>,
|
||||
after: Option<Ulid>,
|
||||
first: Option<usize>,
|
||||
@ -854,7 +854,7 @@ pub async fn get_paginated_user_compat_sso_logins(
|
||||
|
||||
query
|
||||
.push(" WHERE cs.user_id = ")
|
||||
.push_bind(Uuid::from(user.data))
|
||||
.push_bind(Uuid::from(user.id))
|
||||
.generate_pagination("cl.compat_sso_login_id", before, after, first, last)?;
|
||||
|
||||
let span = info_span!(
|
||||
@ -919,7 +919,7 @@ pub async fn get_compat_sso_login_by_token(
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
user.id = %user.data,
|
||||
%user.id,
|
||||
compat_sso_login.id = %login.data,
|
||||
compat_sso_login.redirect_uri = %login.redirect_uri,
|
||||
compat_session.id,
|
||||
@ -931,7 +931,7 @@ pub async fn fullfill_compat_sso_login(
|
||||
conn: impl Acquire<'_, Database = Postgres> + Send,
|
||||
mut rng: impl Rng + Send,
|
||||
clock: &Clock,
|
||||
user: User<PostgresqlBackend>,
|
||||
user: User,
|
||||
mut login: CompatSsoLogin<PostgresqlBackend>,
|
||||
device: Device,
|
||||
) -> Result<CompatSsoLogin<PostgresqlBackend>, anyhow::Error> {
|
||||
@ -943,7 +943,7 @@ pub async fn fullfill_compat_sso_login(
|
||||
|
||||
let created_at = clock.now();
|
||||
let id = Ulid::from_datetime_with_source(created_at.into(), &mut rng);
|
||||
tracing::Span::current().record("user.id", tracing::field::display(user.data));
|
||||
tracing::Span::current().record("compat_session.id", tracing::field::display(id));
|
||||
|
||||
sqlx::query!(
|
||||
r#"
|
||||
@ -951,7 +951,7 @@ pub async fn fullfill_compat_sso_login(
|
||||
VALUES ($1, $2, $3, $4)
|
||||
"#,
|
||||
Uuid::from(id),
|
||||
Uuid::from(user.data),
|
||||
Uuid::from(user.id),
|
||||
device.as_str(),
|
||||
created_at,
|
||||
)
|
||||
|
@ -105,20 +105,13 @@ pub struct DatabaseInconsistencyError;
|
||||
pub struct PostgresqlBackend;
|
||||
|
||||
impl StorageBackend for PostgresqlBackend {
|
||||
type AccessTokenData = Ulid;
|
||||
type AuthenticationData = Ulid;
|
||||
type AuthorizationGrantData = Ulid;
|
||||
type BrowserSessionData = Ulid;
|
||||
type ClientData = Ulid;
|
||||
type CompatAccessTokenData = Ulid;
|
||||
type CompatRefreshTokenData = Ulid;
|
||||
type CompatSessionData = Ulid;
|
||||
type CompatSsoLoginData = Ulid;
|
||||
type RefreshTokenData = Ulid;
|
||||
type SessionData = Ulid;
|
||||
type UserData = Ulid;
|
||||
type UserEmailData = Ulid;
|
||||
type UserEmailVerificationData = Ulid;
|
||||
}
|
||||
|
||||
impl StorageBackendMarker for PostgresqlBackend {}
|
||||
|
@ -29,7 +29,7 @@ use crate::{Clock, DatabaseInconsistencyError, LookupError, PostgresqlBackend};
|
||||
fields(
|
||||
session.id = %session.data,
|
||||
client.id = %session.client.data,
|
||||
user.id = %session.browser_session.user.data,
|
||||
user.id = %session.browser_session.user.id,
|
||||
access_token.id,
|
||||
),
|
||||
err(Debug),
|
||||
@ -178,7 +178,7 @@ pub async fn lookup_active_access_token(
|
||||
res.user_email_confirmed_at,
|
||||
) {
|
||||
(Some(id), Some(email), Some(created_at), confirmed_at) => Some(UserEmail {
|
||||
data: id.into(),
|
||||
id: id.into(),
|
||||
email,
|
||||
created_at,
|
||||
confirmed_at,
|
||||
@ -189,7 +189,7 @@ pub async fn lookup_active_access_token(
|
||||
|
||||
let id = Ulid::from(res.user_id);
|
||||
let user = User {
|
||||
data: id,
|
||||
id,
|
||||
username: res.user_username,
|
||||
sub: id.to_string(),
|
||||
primary_email,
|
||||
@ -201,14 +201,14 @@ pub async fn lookup_active_access_token(
|
||||
) {
|
||||
(None, None) => None,
|
||||
(Some(id), Some(created_at)) => Some(Authentication {
|
||||
data: id.into(),
|
||||
id: id.into(),
|
||||
created_at,
|
||||
}),
|
||||
_ => return Err(DatabaseInconsistencyError.into()),
|
||||
};
|
||||
|
||||
let browser_session = BrowserSession {
|
||||
data: res.user_session_id.into(),
|
||||
id: res.user_session_id.into(),
|
||||
created_at: res.user_session_created_at,
|
||||
user,
|
||||
last_authentication,
|
||||
|
@ -187,7 +187,7 @@ impl GrantLookup {
|
||||
self.user_session_last_authentication_created_at,
|
||||
) {
|
||||
(Some(id), Some(created_at)) => Some(Authentication {
|
||||
data: id.into(),
|
||||
id: id.into(),
|
||||
created_at,
|
||||
}),
|
||||
(None, None) => None,
|
||||
@ -201,7 +201,7 @@ impl GrantLookup {
|
||||
self.user_email_confirmed_at,
|
||||
) {
|
||||
(Some(id), Some(email), Some(created_at), confirmed_at) => Some(UserEmail {
|
||||
data: id.into(),
|
||||
id: id.into(),
|
||||
email,
|
||||
created_at,
|
||||
confirmed_at,
|
||||
@ -230,14 +230,14 @@ impl GrantLookup {
|
||||
) => {
|
||||
let user_id = Ulid::from(user_id);
|
||||
let user = User {
|
||||
data: user_id,
|
||||
id: user_id,
|
||||
username: user_username,
|
||||
sub: user_id.to_string(),
|
||||
primary_email,
|
||||
};
|
||||
|
||||
let browser_session = BrowserSession {
|
||||
data: user_session_id.into(),
|
||||
id: user_session_id.into(),
|
||||
user,
|
||||
created_at: user_session_created_at,
|
||||
last_authentication,
|
||||
@ -500,8 +500,8 @@ pub async fn lookup_grant_by_code(
|
||||
grant.id = %grant.data,
|
||||
client.id = %grant.client.data,
|
||||
session.id,
|
||||
user_session.id = %browser_session.data,
|
||||
user.id = %browser_session.user.data,
|
||||
user_session.id = %browser_session.id,
|
||||
user.id = %browser_session.user.id,
|
||||
),
|
||||
err(Debug),
|
||||
)]
|
||||
@ -510,7 +510,7 @@ pub async fn derive_session(
|
||||
mut rng: impl Rng + Send,
|
||||
clock: &Clock,
|
||||
grant: &AuthorizationGrant<PostgresqlBackend>,
|
||||
browser_session: BrowserSession<PostgresqlBackend>,
|
||||
browser_session: BrowserSession,
|
||||
) -> Result<Session<PostgresqlBackend>, anyhow::Error> {
|
||||
let created_at = clock.now();
|
||||
let id = Ulid::from_datetime_with_source(created_at.into(), &mut rng);
|
||||
@ -532,7 +532,7 @@ pub async fn derive_session(
|
||||
og.oauth2_authorization_grant_id = $4
|
||||
"#,
|
||||
Uuid::from(id),
|
||||
Uuid::from(browser_session.data),
|
||||
Uuid::from(browser_session.id),
|
||||
created_at,
|
||||
Uuid::from(grant.data),
|
||||
)
|
||||
@ -554,8 +554,8 @@ pub async fn derive_session(
|
||||
grant.id = %grant.data,
|
||||
client.id = %grant.client.data,
|
||||
session.id = %session.data,
|
||||
user_session.id = %session.browser_session.data,
|
||||
user.id = %session.browser_session.user.data,
|
||||
user_session.id = %session.browser_session.id,
|
||||
user.id = %session.browser_session.user.id,
|
||||
),
|
||||
err(Debug),
|
||||
)]
|
||||
|
@ -26,14 +26,14 @@ use crate::{Clock, PostgresqlBackend};
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
user.id = %user.data,
|
||||
%user.id,
|
||||
client.id = %client.data,
|
||||
),
|
||||
err(Debug),
|
||||
)]
|
||||
pub async fn fetch_client_consent(
|
||||
executor: impl PgExecutor<'_>,
|
||||
user: &User<PostgresqlBackend>,
|
||||
user: &User,
|
||||
client: &Client<PostgresqlBackend>,
|
||||
) -> Result<Scope, anyhow::Error> {
|
||||
let scope_tokens: Vec<String> = sqlx::query_scalar!(
|
||||
@ -42,7 +42,7 @@ pub async fn fetch_client_consent(
|
||||
FROM oauth2_consents
|
||||
WHERE user_id = $1 AND oauth2_client_id = $2
|
||||
"#,
|
||||
Uuid::from(user.data),
|
||||
Uuid::from(user.id),
|
||||
Uuid::from(client.data),
|
||||
)
|
||||
.fetch_all(executor)
|
||||
@ -59,7 +59,7 @@ pub async fn fetch_client_consent(
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
user.id = %user.data,
|
||||
%user.id,
|
||||
client.id = %client.data,
|
||||
scope = scope.to_string(),
|
||||
),
|
||||
@ -69,7 +69,7 @@ pub async fn insert_client_consent(
|
||||
executor: impl PgExecutor<'_>,
|
||||
mut rng: impl Rng + Send,
|
||||
clock: &Clock,
|
||||
user: &User<PostgresqlBackend>,
|
||||
user: &User,
|
||||
client: &Client<PostgresqlBackend>,
|
||||
scope: &Scope,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
@ -92,7 +92,7 @@ pub async fn insert_client_consent(
|
||||
ON CONFLICT (user_id, oauth2_client_id, scope_token) DO UPDATE SET refreshed_at = $5
|
||||
"#,
|
||||
&ids,
|
||||
Uuid::from(user.data),
|
||||
Uuid::from(user.id),
|
||||
Uuid::from(client.data),
|
||||
&tokens,
|
||||
now,
|
||||
|
@ -38,8 +38,8 @@ pub mod refresh_token;
|
||||
skip_all,
|
||||
fields(
|
||||
session.id = %session.data,
|
||||
user.id = %session.browser_session.user.data,
|
||||
user_session.id = %session.browser_session.data,
|
||||
user.id = %session.browser_session.user.id,
|
||||
user_session.id = %session.browser_session.id,
|
||||
client.id = %session.client.data,
|
||||
),
|
||||
err(Debug),
|
||||
@ -78,14 +78,14 @@ struct OAuthSessionLookup {
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
user.id = %user.data,
|
||||
%user.id,
|
||||
user.username = user.username,
|
||||
),
|
||||
err(Display),
|
||||
)]
|
||||
pub async fn get_paginated_user_oauth_sessions(
|
||||
conn: &mut PgConnection,
|
||||
user: &User<PostgresqlBackend>,
|
||||
user: &User,
|
||||
before: Option<Ulid>,
|
||||
after: Option<Ulid>,
|
||||
first: Option<usize>,
|
||||
@ -108,7 +108,7 @@ pub async fn get_paginated_user_oauth_sessions(
|
||||
|
||||
query
|
||||
.push(" WHERE us.user_id = ")
|
||||
.push_bind(Uuid::from(user.data))
|
||||
.push_bind(Uuid::from(user.id))
|
||||
.generate_pagination("oauth2_session_id", before, after, first, last)?;
|
||||
|
||||
let span = info_span!(
|
||||
@ -135,7 +135,7 @@ pub async fn get_paginated_user_oauth_sessions(
|
||||
|
||||
// TODO: this can generate N queries instead of batching. This is less than
|
||||
// ideal
|
||||
let mut browser_sessions: HashMap<Ulid, BrowserSession<PostgresqlBackend>> = HashMap::new();
|
||||
let mut browser_sessions: HashMap<Ulid, BrowserSession> = HashMap::new();
|
||||
for id in browser_session_ids {
|
||||
let v = lookup_active_session(&mut *conn, id).await?;
|
||||
browser_sessions.insert(id, v);
|
||||
|
@ -30,8 +30,8 @@ use crate::{Clock, DatabaseInconsistencyError, LookupError, PostgresqlBackend};
|
||||
skip_all,
|
||||
fields(
|
||||
session.id = %session.data,
|
||||
user.id = %session.browser_session.user.data,
|
||||
user_session.id = %session.browser_session.data,
|
||||
user.id = %session.browser_session.user.id,
|
||||
user_session.id = %session.browser_session.id,
|
||||
client.id = %session.client.data,
|
||||
refresh_token.id,
|
||||
),
|
||||
@ -206,7 +206,7 @@ pub async fn lookup_active_refresh_token(
|
||||
res.user_email_confirmed_at,
|
||||
) {
|
||||
(Some(id), Some(email), Some(created_at), confirmed_at) => Some(UserEmail {
|
||||
data: id.into(),
|
||||
id: id.into(),
|
||||
email,
|
||||
created_at,
|
||||
confirmed_at,
|
||||
@ -217,7 +217,7 @@ pub async fn lookup_active_refresh_token(
|
||||
|
||||
let id = Ulid::from(res.user_id);
|
||||
let user = User {
|
||||
data: id,
|
||||
id,
|
||||
username: res.user_username,
|
||||
sub: id.to_string(),
|
||||
primary_email,
|
||||
@ -229,14 +229,14 @@ pub async fn lookup_active_refresh_token(
|
||||
) {
|
||||
(None, None) => None,
|
||||
(Some(id), Some(created_at)) => Some(Authentication {
|
||||
data: id.into(),
|
||||
id: id.into(),
|
||||
created_at,
|
||||
}),
|
||||
_ => return Err(DatabaseInconsistencyError.into()),
|
||||
};
|
||||
|
||||
let browser_session = BrowserSession {
|
||||
data: res.user_session_id.into(),
|
||||
id: res.user_session_id.into(),
|
||||
created_at: res.user_session_created_at,
|
||||
user,
|
||||
last_authentication,
|
||||
|
@ -22,7 +22,7 @@ use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
pagination::{process_page, QueryBuilderExt},
|
||||
Clock, GenericLookupError, PostgresqlBackend,
|
||||
Clock, GenericLookupError,
|
||||
};
|
||||
|
||||
#[derive(sqlx::FromRow)]
|
||||
@ -168,7 +168,7 @@ pub async fn add_link(
|
||||
fields(
|
||||
%upstream_oauth_link.id,
|
||||
%upstream_oauth_link.subject,
|
||||
user.id = %user.data,
|
||||
%user.id,
|
||||
%user.username,
|
||||
),
|
||||
err,
|
||||
@ -176,7 +176,7 @@ pub async fn add_link(
|
||||
pub async fn associate_link_to_user(
|
||||
executor: impl PgExecutor<'_>,
|
||||
upstream_oauth_link: &UpstreamOAuthLink,
|
||||
user: &User<PostgresqlBackend>,
|
||||
user: &User,
|
||||
) -> Result<(), sqlx::Error> {
|
||||
sqlx::query!(
|
||||
r#"
|
||||
@ -184,7 +184,7 @@ pub async fn associate_link_to_user(
|
||||
SET user_id = $1
|
||||
WHERE upstream_oauth_link_id = $2
|
||||
"#,
|
||||
Uuid::from(user.data),
|
||||
Uuid::from(user.id),
|
||||
Uuid::from(upstream_oauth_link.id),
|
||||
)
|
||||
.execute(executor)
|
||||
@ -193,10 +193,14 @@ pub async fn associate_link_to_user(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all, err(Display))]
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(%user.id, %user.username),
|
||||
err(Display)
|
||||
)]
|
||||
pub async fn get_paginated_user_links(
|
||||
executor: impl PgExecutor<'_>,
|
||||
user: &User<PostgresqlBackend>,
|
||||
user: &User,
|
||||
before: Option<Ulid>,
|
||||
after: Option<Ulid>,
|
||||
first: Option<usize>,
|
||||
@ -216,7 +220,7 @@ pub async fn get_paginated_user_links(
|
||||
|
||||
query
|
||||
.push(" WHERE user_id = ")
|
||||
.push_bind(Uuid::from(user.data))
|
||||
.push_bind(Uuid::from(user.id))
|
||||
.generate_pagination("upstream_oauth_link_id", before, after, first, last)?;
|
||||
|
||||
let span = info_span!(
|
||||
|
@ -30,7 +30,7 @@ use tracing::{info_span, Instrument};
|
||||
use ulid::Ulid;
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::{DatabaseInconsistencyError, PostgresqlBackend};
|
||||
use super::DatabaseInconsistencyError;
|
||||
use crate::{
|
||||
pagination::{process_page, QueryBuilderExt},
|
||||
Clock, GenericLookupError, LookupError,
|
||||
@ -77,7 +77,7 @@ pub async fn login(
|
||||
clock: &Clock,
|
||||
username: &str,
|
||||
password: &str,
|
||||
) -> Result<BrowserSession<PostgresqlBackend>, LoginError> {
|
||||
) -> Result<BrowserSession, LoginError> {
|
||||
let mut txn = conn.begin().await.context("could not start transaction")?;
|
||||
let user = lookup_user_by_username(&mut txn, username)
|
||||
.await
|
||||
@ -137,10 +137,10 @@ struct SessionLookup {
|
||||
user_email_confirmed_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
impl TryInto<BrowserSession<PostgresqlBackend>> for SessionLookup {
|
||||
impl TryInto<BrowserSession> for SessionLookup {
|
||||
type Error = DatabaseInconsistencyError;
|
||||
|
||||
fn try_into(self) -> Result<BrowserSession<PostgresqlBackend>, Self::Error> {
|
||||
fn try_into(self) -> Result<BrowserSession, Self::Error> {
|
||||
let primary_email = match (
|
||||
self.user_email_id,
|
||||
self.user_email,
|
||||
@ -148,7 +148,7 @@ impl TryInto<BrowserSession<PostgresqlBackend>> for SessionLookup {
|
||||
self.user_email_confirmed_at,
|
||||
) {
|
||||
(Some(id), Some(email), Some(created_at), confirmed_at) => Some(UserEmail {
|
||||
data: id.into(),
|
||||
id: id.into(),
|
||||
email,
|
||||
created_at,
|
||||
confirmed_at,
|
||||
@ -159,7 +159,7 @@ impl TryInto<BrowserSession<PostgresqlBackend>> for SessionLookup {
|
||||
|
||||
let id = Ulid::from(self.user_id);
|
||||
let user = User {
|
||||
data: id,
|
||||
id,
|
||||
username: self.username,
|
||||
sub: id.to_string(),
|
||||
primary_email,
|
||||
@ -167,7 +167,7 @@ impl TryInto<BrowserSession<PostgresqlBackend>> for SessionLookup {
|
||||
|
||||
let last_authentication = match (self.last_authentication_id, self.last_authd_at) {
|
||||
(Some(id), Some(created_at)) => Some(Authentication {
|
||||
data: id.into(),
|
||||
id: id.into(),
|
||||
created_at,
|
||||
}),
|
||||
(None, None) => None,
|
||||
@ -175,7 +175,7 @@ impl TryInto<BrowserSession<PostgresqlBackend>> for SessionLookup {
|
||||
};
|
||||
|
||||
Ok(BrowserSession {
|
||||
data: self.user_session_id.into(),
|
||||
id: self.user_session_id.into(),
|
||||
user,
|
||||
created_at: self.created_at,
|
||||
last_authentication,
|
||||
@ -191,7 +191,7 @@ impl TryInto<BrowserSession<PostgresqlBackend>> for SessionLookup {
|
||||
pub async fn lookup_active_session(
|
||||
executor: impl PgExecutor<'_>,
|
||||
id: Ulid,
|
||||
) -> Result<BrowserSession<PostgresqlBackend>, ActiveSessionLookupError> {
|
||||
) -> Result<BrowserSession, ActiveSessionLookupError> {
|
||||
let res = sqlx::query_as!(
|
||||
SessionLookup,
|
||||
r#"
|
||||
@ -229,19 +229,19 @@ pub async fn lookup_active_session(
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
user.id = %user.data,
|
||||
user.username = user.username,
|
||||
%user.id,
|
||||
%user.username,
|
||||
),
|
||||
err(Display),
|
||||
)]
|
||||
pub async fn get_paginated_user_sessions(
|
||||
executor: impl PgExecutor<'_>,
|
||||
user: &User<PostgresqlBackend>,
|
||||
user: &User,
|
||||
before: Option<Ulid>,
|
||||
after: Option<Ulid>,
|
||||
first: Option<usize>,
|
||||
last: Option<usize>,
|
||||
) -> Result<(bool, bool, Vec<BrowserSession<PostgresqlBackend>>), anyhow::Error> {
|
||||
) -> Result<(bool, bool, Vec<BrowserSession>), anyhow::Error> {
|
||||
let mut query = QueryBuilder::new(
|
||||
r#"
|
||||
SELECT
|
||||
@ -267,7 +267,7 @@ pub async fn get_paginated_user_sessions(
|
||||
|
||||
query
|
||||
.push(" WHERE s.finished_at IS NULL AND s.user_id = ")
|
||||
.push_bind(Uuid::from(user.data))
|
||||
.push_bind(Uuid::from(user.id))
|
||||
.generate_pagination("s.user_session_id", before, after, first, last)?;
|
||||
|
||||
let span = info_span!("Fetch paginated user emails", db.statement = query.sql());
|
||||
@ -286,7 +286,7 @@ pub async fn get_paginated_user_sessions(
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
user.id = %user.data,
|
||||
%user.id,
|
||||
user_session.id,
|
||||
),
|
||||
err(Display),
|
||||
@ -295,8 +295,8 @@ pub async fn start_session(
|
||||
executor: impl PgExecutor<'_>,
|
||||
mut rng: impl Rng + Send,
|
||||
clock: &Clock,
|
||||
user: User<PostgresqlBackend>,
|
||||
) -> Result<BrowserSession<PostgresqlBackend>, anyhow::Error> {
|
||||
user: User,
|
||||
) -> Result<BrowserSession, anyhow::Error> {
|
||||
let created_at = clock.now();
|
||||
let id = Ulid::from_datetime_with_source(created_at.into(), &mut rng);
|
||||
tracing::Span::current().record("user_session.id", tracing::field::display(id));
|
||||
@ -307,7 +307,7 @@ pub async fn start_session(
|
||||
VALUES ($1, $2, $3)
|
||||
"#,
|
||||
Uuid::from(id),
|
||||
Uuid::from(user.data),
|
||||
Uuid::from(user.id),
|
||||
created_at,
|
||||
)
|
||||
.execute(executor)
|
||||
@ -315,7 +315,7 @@ pub async fn start_session(
|
||||
.context("could not create session")?;
|
||||
|
||||
let session = BrowserSession {
|
||||
data: id,
|
||||
id,
|
||||
user,
|
||||
created_at,
|
||||
last_authentication: None,
|
||||
@ -326,12 +326,12 @@ pub async fn start_session(
|
||||
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(user.id = %user.data),
|
||||
fields(%user.id),
|
||||
err(Display),
|
||||
)]
|
||||
pub async fn count_active_sessions(
|
||||
executor: impl PgExecutor<'_>,
|
||||
user: &User<PostgresqlBackend>,
|
||||
user: &User,
|
||||
) -> Result<usize, anyhow::Error> {
|
||||
let res = sqlx::query_scalar!(
|
||||
r#"
|
||||
@ -339,7 +339,7 @@ pub async fn count_active_sessions(
|
||||
FROM user_sessions s
|
||||
WHERE s.user_id = $1 AND s.finished_at IS NULL
|
||||
"#,
|
||||
Uuid::from(user.data),
|
||||
Uuid::from(user.id),
|
||||
)
|
||||
.fetch_one(executor)
|
||||
.await?
|
||||
@ -366,8 +366,8 @@ pub enum AuthenticationError {
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
user.id = %session.user.data,
|
||||
user_session.id = %session.data,
|
||||
user.id = %user_session.user.id,
|
||||
%user_session.id,
|
||||
user_session_authentication.id,
|
||||
),
|
||||
err,
|
||||
@ -376,7 +376,7 @@ pub async fn authenticate_session(
|
||||
txn: &mut Transaction<'_, Postgres>,
|
||||
mut rng: impl Rng + Send,
|
||||
clock: &Clock,
|
||||
session: &mut BrowserSession<PostgresqlBackend>,
|
||||
user_session: &mut BrowserSession,
|
||||
password: &str,
|
||||
) -> Result<(), AuthenticationError> {
|
||||
// First, fetch the hashed password from the user associated with that session
|
||||
@ -388,7 +388,7 @@ pub async fn authenticate_session(
|
||||
ORDER BY up.created_at DESC
|
||||
LIMIT 1
|
||||
"#,
|
||||
Uuid::from(session.user.data),
|
||||
Uuid::from(user_session.user.id),
|
||||
)
|
||||
.fetch_one(txn.borrow_mut())
|
||||
.instrument(tracing::info_span!("Lookup hashed password"))
|
||||
@ -423,7 +423,7 @@ pub async fn authenticate_session(
|
||||
VALUES ($1, $2, $3)
|
||||
"#,
|
||||
Uuid::from(id),
|
||||
Uuid::from(session.data),
|
||||
Uuid::from(user_session.id),
|
||||
created_at,
|
||||
)
|
||||
.execute(txn.borrow_mut())
|
||||
@ -431,10 +431,7 @@ pub async fn authenticate_session(
|
||||
.await
|
||||
.map_err(AuthenticationError::Save)?;
|
||||
|
||||
session.last_authentication = Some(Authentication {
|
||||
data: id,
|
||||
created_at,
|
||||
});
|
||||
user_session.last_authentication = Some(Authentication { id, created_at });
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -442,9 +439,9 @@ pub async fn authenticate_session(
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
user.id = %session.user.data,
|
||||
user.id = %user_session.user.id,
|
||||
%upstream_oauth_link.id,
|
||||
user_session.id = %session.data,
|
||||
%user_session.id,
|
||||
user_session_authentication.id,
|
||||
),
|
||||
err,
|
||||
@ -453,7 +450,7 @@ pub async fn authenticate_session_with_upstream(
|
||||
executor: impl PgExecutor<'_>,
|
||||
mut rng: impl Rng + Send,
|
||||
clock: &Clock,
|
||||
session: &mut BrowserSession<PostgresqlBackend>,
|
||||
user_session: &mut BrowserSession,
|
||||
upstream_oauth_link: &UpstreamOAuthLink,
|
||||
) -> Result<(), sqlx::Error> {
|
||||
let created_at = clock.now();
|
||||
@ -470,17 +467,14 @@ pub async fn authenticate_session_with_upstream(
|
||||
VALUES ($1, $2, $3)
|
||||
"#,
|
||||
Uuid::from(id),
|
||||
Uuid::from(session.data),
|
||||
Uuid::from(user_session.id),
|
||||
created_at,
|
||||
)
|
||||
.execute(executor)
|
||||
.instrument(tracing::info_span!("Save authentication"))
|
||||
.await?;
|
||||
|
||||
session.last_authentication = Some(Authentication {
|
||||
data: id,
|
||||
created_at,
|
||||
});
|
||||
user_session.last_authentication = Some(Authentication { id, created_at });
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -500,7 +494,7 @@ pub async fn register_user(
|
||||
phf: impl PasswordHasher + Send,
|
||||
username: &str,
|
||||
password: &str,
|
||||
) -> Result<User<PostgresqlBackend>, anyhow::Error> {
|
||||
) -> Result<User, anyhow::Error> {
|
||||
let created_at = clock.now();
|
||||
let id = Ulid::from_datetime_with_source(created_at.into(), &mut rng);
|
||||
tracing::Span::current().record("user.id", tracing::field::display(id));
|
||||
@ -520,7 +514,7 @@ pub async fn register_user(
|
||||
.context("could not insert user")?;
|
||||
|
||||
let user = User {
|
||||
data: id,
|
||||
id,
|
||||
username: username.to_owned(),
|
||||
sub: id.to_string(),
|
||||
primary_email: None,
|
||||
@ -544,7 +538,7 @@ pub async fn register_passwordless_user(
|
||||
mut rng: impl Rng + Send,
|
||||
clock: &Clock,
|
||||
username: &str,
|
||||
) -> Result<User<PostgresqlBackend>, sqlx::Error> {
|
||||
) -> Result<User, sqlx::Error> {
|
||||
let created_at = clock.now();
|
||||
let id = Ulid::from_datetime_with_source(created_at.into(), &mut rng);
|
||||
tracing::Span::current().record("user.id", tracing::field::display(id));
|
||||
@ -562,7 +556,7 @@ pub async fn register_passwordless_user(
|
||||
.await?;
|
||||
|
||||
Ok(User {
|
||||
data: id,
|
||||
id,
|
||||
username: username.to_owned(),
|
||||
sub: id.to_string(),
|
||||
primary_email: None,
|
||||
@ -572,7 +566,7 @@ pub async fn register_passwordless_user(
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
user.id = %user.data,
|
||||
%user.id,
|
||||
user_password.id,
|
||||
),
|
||||
err(Display),
|
||||
@ -582,7 +576,7 @@ pub async fn set_password(
|
||||
mut rng: impl CryptoRng + Rng + Send,
|
||||
clock: &Clock,
|
||||
phf: impl PasswordHasher + Send,
|
||||
user: &User<PostgresqlBackend>,
|
||||
user: &User,
|
||||
password: &str,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let created_at = clock.now();
|
||||
@ -598,7 +592,7 @@ pub async fn set_password(
|
||||
VALUES ($1, $2, $3, $4)
|
||||
"#,
|
||||
Uuid::from(id),
|
||||
Uuid::from(user.data),
|
||||
Uuid::from(user.id),
|
||||
hashed_password.to_string(),
|
||||
created_at,
|
||||
)
|
||||
@ -612,13 +606,13 @@ pub async fn set_password(
|
||||
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(user_session.id = %session.data),
|
||||
fields(%user_session.id),
|
||||
err(Display),
|
||||
)]
|
||||
pub async fn end_session(
|
||||
executor: impl PgExecutor<'_>,
|
||||
clock: &Clock,
|
||||
session: &BrowserSession<PostgresqlBackend>,
|
||||
user_session: &BrowserSession,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let now = clock.now();
|
||||
let res = sqlx::query!(
|
||||
@ -628,7 +622,7 @@ pub async fn end_session(
|
||||
WHERE user_session_id = $2
|
||||
"#,
|
||||
now,
|
||||
Uuid::from(session.data),
|
||||
Uuid::from(user_session.id),
|
||||
)
|
||||
.execute(executor)
|
||||
.instrument(info_span!("End session"))
|
||||
@ -663,7 +657,7 @@ impl LookupError for UserLookupError {
|
||||
pub async fn lookup_user_by_username(
|
||||
executor: impl PgExecutor<'_>,
|
||||
username: &str,
|
||||
) -> Result<User<PostgresqlBackend>, UserLookupError> {
|
||||
) -> Result<User, UserLookupError> {
|
||||
let res = sqlx::query_as!(
|
||||
UserLookup,
|
||||
r#"
|
||||
@ -694,7 +688,7 @@ pub async fn lookup_user_by_username(
|
||||
res.user_email_confirmed_at,
|
||||
) {
|
||||
(Some(id), Some(email), Some(created_at), confirmed_at) => Some(UserEmail {
|
||||
data: id.into(),
|
||||
id: id.into(),
|
||||
email,
|
||||
created_at,
|
||||
confirmed_at,
|
||||
@ -705,7 +699,7 @@ pub async fn lookup_user_by_username(
|
||||
|
||||
let id = Ulid::from(res.user_id);
|
||||
Ok(User {
|
||||
data: id,
|
||||
id,
|
||||
username: res.user_username,
|
||||
sub: id.to_string(),
|
||||
primary_email,
|
||||
@ -717,10 +711,7 @@ pub async fn lookup_user_by_username(
|
||||
fields(user.id = %id),
|
||||
err,
|
||||
)]
|
||||
pub async fn lookup_user(
|
||||
executor: impl PgExecutor<'_>,
|
||||
id: Ulid,
|
||||
) -> Result<User<PostgresqlBackend>, UserLookupError> {
|
||||
pub async fn lookup_user(executor: impl PgExecutor<'_>, id: Ulid) -> Result<User, UserLookupError> {
|
||||
let res = sqlx::query_as!(
|
||||
UserLookup,
|
||||
r#"
|
||||
@ -751,7 +742,7 @@ pub async fn lookup_user(
|
||||
res.user_email_confirmed_at,
|
||||
) {
|
||||
(Some(id), Some(email), Some(created_at), confirmed_at) => Some(UserEmail {
|
||||
data: id.into(),
|
||||
id: id.into(),
|
||||
email,
|
||||
created_at,
|
||||
confirmed_at,
|
||||
@ -762,7 +753,7 @@ pub async fn lookup_user(
|
||||
|
||||
let id = Ulid::from(res.user_id);
|
||||
Ok(User {
|
||||
data: id,
|
||||
id,
|
||||
username: res.user_username,
|
||||
sub: id.to_string(),
|
||||
primary_email,
|
||||
@ -798,10 +789,10 @@ struct UserEmailLookup {
|
||||
user_email_confirmed_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
impl From<UserEmailLookup> for UserEmail<PostgresqlBackend> {
|
||||
fn from(e: UserEmailLookup) -> UserEmail<PostgresqlBackend> {
|
||||
impl From<UserEmailLookup> for UserEmail {
|
||||
fn from(e: UserEmailLookup) -> UserEmail {
|
||||
UserEmail {
|
||||
data: e.user_email_id.into(),
|
||||
id: e.user_email_id.into(),
|
||||
email: e.user_email,
|
||||
created_at: e.user_email_created_at,
|
||||
confirmed_at: e.user_email_confirmed_at,
|
||||
@ -811,13 +802,13 @@ impl From<UserEmailLookup> for UserEmail<PostgresqlBackend> {
|
||||
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(user.id = %user.data, user.username = user.username),
|
||||
fields(%user.id, %user.username),
|
||||
err(Display),
|
||||
)]
|
||||
pub async fn get_user_emails(
|
||||
executor: impl PgExecutor<'_>,
|
||||
user: &User<PostgresqlBackend>,
|
||||
) -> Result<Vec<UserEmail<PostgresqlBackend>>, anyhow::Error> {
|
||||
user: &User,
|
||||
) -> Result<Vec<UserEmail>, anyhow::Error> {
|
||||
let res = sqlx::query_as!(
|
||||
UserEmailLookup,
|
||||
r#"
|
||||
@ -832,7 +823,7 @@ pub async fn get_user_emails(
|
||||
|
||||
ORDER BY ue.email ASC
|
||||
"#,
|
||||
Uuid::from(user.data),
|
||||
Uuid::from(user.id),
|
||||
)
|
||||
.fetch_all(executor)
|
||||
.instrument(info_span!("Fetch user emails"))
|
||||
@ -843,12 +834,12 @@ pub async fn get_user_emails(
|
||||
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(user.id = %user.data, user.username = user.username),
|
||||
fields(%user.id, %user.username),
|
||||
err(Display),
|
||||
)]
|
||||
pub async fn count_user_emails(
|
||||
executor: impl PgExecutor<'_>,
|
||||
user: &User<PostgresqlBackend>,
|
||||
user: &User,
|
||||
) -> Result<i64, anyhow::Error> {
|
||||
let res = sqlx::query_scalar!(
|
||||
r#"
|
||||
@ -856,7 +847,7 @@ pub async fn count_user_emails(
|
||||
FROM user_emails ue
|
||||
WHERE ue.user_id = $1
|
||||
"#,
|
||||
Uuid::from(user.data),
|
||||
Uuid::from(user.id),
|
||||
)
|
||||
.fetch_one(executor)
|
||||
.instrument(info_span!("Count user emails"))
|
||||
@ -867,20 +858,17 @@ pub async fn count_user_emails(
|
||||
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
user.id = %user.data,
|
||||
user.username = user.username,
|
||||
),
|
||||
fields(%user.id, %user.username),
|
||||
err(Display),
|
||||
)]
|
||||
pub async fn get_paginated_user_emails(
|
||||
executor: impl PgExecutor<'_>,
|
||||
user: &User<PostgresqlBackend>,
|
||||
user: &User,
|
||||
before: Option<Ulid>,
|
||||
after: Option<Ulid>,
|
||||
first: Option<usize>,
|
||||
last: Option<usize>,
|
||||
) -> Result<(bool, bool, Vec<UserEmail<PostgresqlBackend>>), anyhow::Error> {
|
||||
) -> Result<(bool, bool, Vec<UserEmail>), anyhow::Error> {
|
||||
let mut query = QueryBuilder::new(
|
||||
r#"
|
||||
SELECT
|
||||
@ -894,7 +882,7 @@ pub async fn get_paginated_user_emails(
|
||||
|
||||
query
|
||||
.push(" WHERE ue.user_id = ")
|
||||
.push_bind(Uuid::from(user.data))
|
||||
.push_bind(Uuid::from(user.id))
|
||||
.generate_pagination("ue.user_email_id", before, after, first, last)?;
|
||||
|
||||
let span = info_span!("Fetch paginated user sessions", db.statement = query.sql());
|
||||
@ -916,17 +904,17 @@ pub async fn get_paginated_user_emails(
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
user.id = %user.data,
|
||||
user.username = user.username,
|
||||
%user.id,
|
||||
%user.username,
|
||||
user_email.id = %id,
|
||||
),
|
||||
err(Display),
|
||||
)]
|
||||
pub async fn get_user_email(
|
||||
executor: impl PgExecutor<'_>,
|
||||
user: &User<PostgresqlBackend>,
|
||||
user: &User,
|
||||
id: Ulid,
|
||||
) -> Result<UserEmail<PostgresqlBackend>, anyhow::Error> {
|
||||
) -> Result<UserEmail, anyhow::Error> {
|
||||
let res = sqlx::query_as!(
|
||||
UserEmailLookup,
|
||||
r#"
|
||||
@ -940,7 +928,7 @@ pub async fn get_user_email(
|
||||
WHERE ue.user_id = $1
|
||||
AND ue.user_email_id = $2
|
||||
"#,
|
||||
Uuid::from(user.data),
|
||||
Uuid::from(user.id),
|
||||
Uuid::from(id),
|
||||
)
|
||||
.fetch_one(executor)
|
||||
@ -953,8 +941,8 @@ pub async fn get_user_email(
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
user.id = %user.data,
|
||||
user.username = user.username,
|
||||
%user.id,
|
||||
%user.username,
|
||||
user_email.id,
|
||||
user_email.email = %email,
|
||||
),
|
||||
@ -964,9 +952,9 @@ pub async fn add_user_email(
|
||||
executor: impl PgExecutor<'_>,
|
||||
mut rng: impl Rng + Send,
|
||||
clock: &Clock,
|
||||
user: &User<PostgresqlBackend>,
|
||||
user: &User,
|
||||
email: String,
|
||||
) -> Result<UserEmail<PostgresqlBackend>, anyhow::Error> {
|
||||
) -> Result<UserEmail, anyhow::Error> {
|
||||
let created_at = clock.now();
|
||||
let id = Ulid::from_datetime_with_source(created_at.into(), &mut rng);
|
||||
tracing::Span::current().record("user_email.id", tracing::field::display(id));
|
||||
@ -977,7 +965,7 @@ pub async fn add_user_email(
|
||||
VALUES ($1, $2, $3, $4)
|
||||
"#,
|
||||
Uuid::from(id),
|
||||
Uuid::from(user.data),
|
||||
Uuid::from(user.id),
|
||||
&email,
|
||||
created_at,
|
||||
)
|
||||
@ -987,7 +975,7 @@ pub async fn add_user_email(
|
||||
.context("could not insert user email")?;
|
||||
|
||||
Ok(UserEmail {
|
||||
data: id,
|
||||
id,
|
||||
email,
|
||||
created_at,
|
||||
confirmed_at: None,
|
||||
@ -997,14 +985,14 @@ pub async fn add_user_email(
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
user_email.id = %email.data,
|
||||
user_email.email = %email.email,
|
||||
%user_email.id,
|
||||
%user_email.email,
|
||||
),
|
||||
err(Display),
|
||||
)]
|
||||
pub async fn set_user_email_as_primary(
|
||||
executor: impl PgExecutor<'_>,
|
||||
email: &UserEmail<PostgresqlBackend>,
|
||||
user_email: &UserEmail,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
sqlx::query!(
|
||||
r#"
|
||||
@ -1014,7 +1002,7 @@ pub async fn set_user_email_as_primary(
|
||||
WHERE user_emails.user_email_id = $1
|
||||
AND users.user_id = user_emails.user_id
|
||||
"#,
|
||||
Uuid::from(email.data),
|
||||
Uuid::from(user_email.id),
|
||||
)
|
||||
.execute(executor)
|
||||
.instrument(info_span!("Add user email"))
|
||||
@ -1027,21 +1015,21 @@ pub async fn set_user_email_as_primary(
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
user_email.id = %email.data,
|
||||
user_email.email = %email.email,
|
||||
%user_email.id,
|
||||
%user_email.email,
|
||||
),
|
||||
err(Display),
|
||||
)]
|
||||
pub async fn remove_user_email(
|
||||
executor: impl PgExecutor<'_>,
|
||||
email: UserEmail<PostgresqlBackend>,
|
||||
user_email: UserEmail,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
sqlx::query!(
|
||||
r#"
|
||||
DELETE FROM user_emails
|
||||
WHERE user_emails.user_email_id = $1
|
||||
"#,
|
||||
Uuid::from(email.data),
|
||||
Uuid::from(user_email.id),
|
||||
)
|
||||
.execute(executor)
|
||||
.instrument(info_span!("Remove user email"))
|
||||
@ -1054,16 +1042,16 @@ pub async fn remove_user_email(
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
user.id = %user.data,
|
||||
%user.id,
|
||||
user_email.email = email,
|
||||
),
|
||||
err(Display),
|
||||
)]
|
||||
pub async fn lookup_user_email(
|
||||
executor: impl PgExecutor<'_>,
|
||||
user: &User<PostgresqlBackend>,
|
||||
user: &User,
|
||||
email: &str,
|
||||
) -> Result<UserEmail<PostgresqlBackend>, anyhow::Error> {
|
||||
) -> Result<UserEmail, anyhow::Error> {
|
||||
let res = sqlx::query_as!(
|
||||
UserEmailLookup,
|
||||
r#"
|
||||
@ -1077,7 +1065,7 @@ pub async fn lookup_user_email(
|
||||
WHERE ue.user_id = $1
|
||||
AND ue.email = $2
|
||||
"#,
|
||||
Uuid::from(user.data),
|
||||
Uuid::from(user.id),
|
||||
email,
|
||||
)
|
||||
.fetch_one(executor)
|
||||
@ -1091,16 +1079,16 @@ pub async fn lookup_user_email(
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
user.id = %user.data,
|
||||
%user.id,
|
||||
user_email.id = %id,
|
||||
),
|
||||
err,
|
||||
)]
|
||||
pub async fn lookup_user_email_by_id(
|
||||
executor: impl PgExecutor<'_>,
|
||||
user: &User<PostgresqlBackend>,
|
||||
user: &User,
|
||||
id: Ulid,
|
||||
) -> Result<UserEmail<PostgresqlBackend>, GenericLookupError> {
|
||||
) -> Result<UserEmail, GenericLookupError> {
|
||||
let res = sqlx::query_as!(
|
||||
UserEmailLookup,
|
||||
r#"
|
||||
@ -1114,7 +1102,7 @@ pub async fn lookup_user_email_by_id(
|
||||
WHERE ue.user_id = $1
|
||||
AND ue.user_email_id = $2
|
||||
"#,
|
||||
Uuid::from(user.data),
|
||||
Uuid::from(user.id),
|
||||
Uuid::from(id),
|
||||
)
|
||||
.fetch_one(executor)
|
||||
@ -1127,16 +1115,14 @@ pub async fn lookup_user_email_by_id(
|
||||
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
user_email.id = %email.data,
|
||||
),
|
||||
fields(%user_email.id),
|
||||
err(Display),
|
||||
)]
|
||||
pub async fn mark_user_email_as_verified(
|
||||
executor: impl PgExecutor<'_>,
|
||||
clock: &Clock,
|
||||
mut email: UserEmail<PostgresqlBackend>,
|
||||
) -> Result<UserEmail<PostgresqlBackend>, anyhow::Error> {
|
||||
mut user_email: UserEmail,
|
||||
) -> Result<UserEmail, anyhow::Error> {
|
||||
let confirmed_at = clock.now();
|
||||
sqlx::query!(
|
||||
r#"
|
||||
@ -1144,7 +1130,7 @@ pub async fn mark_user_email_as_verified(
|
||||
SET confirmed_at = $2
|
||||
WHERE user_email_id = $1
|
||||
"#,
|
||||
Uuid::from(email.data),
|
||||
Uuid::from(user_email.id),
|
||||
confirmed_at,
|
||||
)
|
||||
.execute(executor)
|
||||
@ -1152,9 +1138,9 @@ pub async fn mark_user_email_as_verified(
|
||||
.await
|
||||
.context("could not update user email")?;
|
||||
|
||||
email.confirmed_at = Some(confirmed_at);
|
||||
user_email.confirmed_at = Some(confirmed_at);
|
||||
|
||||
Ok(email)
|
||||
Ok(user_email)
|
||||
}
|
||||
|
||||
struct UserEmailConfirmationCodeLookup {
|
||||
@ -1167,17 +1153,15 @@ struct UserEmailConfirmationCodeLookup {
|
||||
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
user_email.id = %email.data,
|
||||
),
|
||||
fields(%user_email.id),
|
||||
err(Display),
|
||||
)]
|
||||
pub async fn lookup_user_email_verification_code(
|
||||
executor: impl PgExecutor<'_>,
|
||||
clock: &Clock,
|
||||
email: UserEmail<PostgresqlBackend>,
|
||||
user_email: UserEmail,
|
||||
code: &str,
|
||||
) -> Result<UserEmailVerification<PostgresqlBackend>, anyhow::Error> {
|
||||
) -> Result<UserEmailVerification, anyhow::Error> {
|
||||
let now = clock.now();
|
||||
|
||||
let res = sqlx::query_as!(
|
||||
@ -1194,7 +1178,7 @@ pub async fn lookup_user_email_verification_code(
|
||||
AND ec.user_email_id = $2
|
||||
"#,
|
||||
code,
|
||||
Uuid::from(email.data),
|
||||
Uuid::from(user_email.id),
|
||||
)
|
||||
.fetch_one(executor)
|
||||
.instrument(info_span!("Lookup user email verification"))
|
||||
@ -1212,9 +1196,9 @@ pub async fn lookup_user_email_verification_code(
|
||||
};
|
||||
|
||||
Ok(UserEmailVerification {
|
||||
data: res.user_email_confirmation_code_id.into(),
|
||||
id: res.user_email_confirmation_code_id.into(),
|
||||
code: res.code,
|
||||
email,
|
||||
email: user_email,
|
||||
state,
|
||||
created_at: res.created_at,
|
||||
})
|
||||
@ -1223,16 +1207,19 @@ pub async fn lookup_user_email_verification_code(
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
user_email_verification.id = %verification.data,
|
||||
%user_email_verification.id,
|
||||
),
|
||||
err(Display),
|
||||
)]
|
||||
pub async fn consume_email_verification(
|
||||
executor: impl PgExecutor<'_>,
|
||||
clock: &Clock,
|
||||
mut verification: UserEmailVerification<PostgresqlBackend>,
|
||||
) -> Result<UserEmailVerification<PostgresqlBackend>, anyhow::Error> {
|
||||
if !matches!(verification.state, UserEmailVerificationState::Valid) {
|
||||
mut user_email_verification: UserEmailVerification,
|
||||
) -> Result<UserEmailVerification, anyhow::Error> {
|
||||
if !matches!(
|
||||
user_email_verification.state,
|
||||
UserEmailVerificationState::Valid
|
||||
) {
|
||||
bail!("user email verification in wrong state");
|
||||
}
|
||||
|
||||
@ -1244,7 +1231,7 @@ pub async fn consume_email_verification(
|
||||
SET consumed_at = $2
|
||||
WHERE user_email_confirmation_code_id = $1
|
||||
"#,
|
||||
Uuid::from(verification.data),
|
||||
Uuid::from(user_email_verification.id),
|
||||
consumed_at
|
||||
)
|
||||
.execute(executor)
|
||||
@ -1252,16 +1239,16 @@ pub async fn consume_email_verification(
|
||||
.await
|
||||
.context("could not update user email verification")?;
|
||||
|
||||
verification.state = UserEmailVerificationState::AlreadyUsed { when: consumed_at };
|
||||
user_email_verification.state = UserEmailVerificationState::AlreadyUsed { when: consumed_at };
|
||||
|
||||
Ok(verification)
|
||||
Ok(user_email_verification)
|
||||
}
|
||||
|
||||
#[tracing::instrument(
|
||||
skip_all,
|
||||
fields(
|
||||
user_email.id = %email.data,
|
||||
user_email.email = %email.email,
|
||||
%user_email.id,
|
||||
%user_email.email,
|
||||
user_email_confirmation.id,
|
||||
user_email_confirmation.code = code,
|
||||
),
|
||||
@ -1271,10 +1258,10 @@ pub async fn add_user_email_verification_code(
|
||||
executor: impl PgExecutor<'_>,
|
||||
mut rng: impl Rng + Send,
|
||||
clock: &Clock,
|
||||
email: UserEmail<PostgresqlBackend>,
|
||||
user_email: UserEmail,
|
||||
max_age: chrono::Duration,
|
||||
code: String,
|
||||
) -> Result<UserEmailVerification<PostgresqlBackend>, anyhow::Error> {
|
||||
) -> Result<UserEmailVerification, anyhow::Error> {
|
||||
let created_at = clock.now();
|
||||
let id = Ulid::from_datetime_with_source(created_at.into(), &mut rng);
|
||||
tracing::Span::current().record("user_email_confirmation.id", tracing::field::display(id));
|
||||
@ -1287,7 +1274,7 @@ pub async fn add_user_email_verification_code(
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
"#,
|
||||
Uuid::from(id),
|
||||
Uuid::from(email.data),
|
||||
Uuid::from(user_email.id),
|
||||
code,
|
||||
created_at,
|
||||
expires_at,
|
||||
@ -1298,8 +1285,8 @@ pub async fn add_user_email_verification_code(
|
||||
.context("could not insert user email verification code")?;
|
||||
|
||||
let verification = UserEmailVerification {
|
||||
data: id,
|
||||
email,
|
||||
id,
|
||||
email: user_email,
|
||||
code,
|
||||
created_at,
|
||||
state: UserEmailVerificationState::Valid,
|
||||
@ -1331,10 +1318,10 @@ mod tests {
|
||||
assert!(exists);
|
||||
|
||||
let session = login(&mut txn, &mut rng, &clock, "john", "hunter2").await?;
|
||||
assert_eq!(session.user.data, user.data);
|
||||
assert_eq!(session.user.id, user.id);
|
||||
|
||||
let user2 = lookup_user_by_username(&mut txn, "john").await?;
|
||||
assert_eq!(user.data, user2.data);
|
||||
assert_eq!(user.id, user2.id);
|
||||
|
||||
txn.commit().await?;
|
||||
|
||||
|
Reference in New Issue
Block a user