Don't parse the user agent unless we need to
This commit is contained in:
@@ -11,7 +11,7 @@ use serde::Serialize;
|
||||
use ulid::Ulid;
|
||||
|
||||
use super::Device;
|
||||
use crate::{InvalidTransitionError, UserAgent};
|
||||
use crate::InvalidTransitionError;
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)]
|
||||
pub enum CompatSessionState {
|
||||
@@ -76,7 +76,7 @@ pub struct CompatSession {
|
||||
pub user_session_id: Option<Ulid>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub is_synapse_admin: bool,
|
||||
pub user_agent: Option<UserAgent>,
|
||||
pub user_agent: Option<String>,
|
||||
pub last_active_at: Option<DateTime<Utc>>,
|
||||
pub last_active_ip: Option<IpAddr>,
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ use oauth2_types::scope::Scope;
|
||||
use serde::Serialize;
|
||||
use ulid::Ulid;
|
||||
|
||||
use crate::{BrowserSession, InvalidTransitionError, Session, UserAgent};
|
||||
use crate::{BrowserSession, InvalidTransitionError, Session};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
|
||||
#[serde(rename_all = "snake_case", tag = "state")]
|
||||
@@ -192,7 +192,7 @@ pub struct DeviceCodeGrant {
|
||||
pub ip_address: Option<IpAddr>,
|
||||
|
||||
/// The user agent used to request this device code grant.
|
||||
pub user_agent: Option<UserAgent>,
|
||||
pub user_agent: Option<String>,
|
||||
}
|
||||
|
||||
impl std::ops::Deref for DeviceCodeGrant {
|
||||
|
||||
@@ -11,7 +11,7 @@ use oauth2_types::scope::Scope;
|
||||
use serde::Serialize;
|
||||
use ulid::Ulid;
|
||||
|
||||
use crate::{InvalidTransitionError, UserAgent};
|
||||
use crate::InvalidTransitionError;
|
||||
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)]
|
||||
pub enum SessionState {
|
||||
@@ -80,7 +80,7 @@ pub struct Session {
|
||||
pub user_session_id: Option<Ulid>,
|
||||
pub client_id: Ulid,
|
||||
pub scope: Scope,
|
||||
pub user_agent: Option<UserAgent>,
|
||||
pub user_agent: Option<String>,
|
||||
pub last_active_at: Option<DateTime<Utc>>,
|
||||
pub last_active_ip: Option<IpAddr>,
|
||||
}
|
||||
|
||||
@@ -12,8 +12,6 @@ use serde::Serialize;
|
||||
use ulid::Ulid;
|
||||
use url::Url;
|
||||
|
||||
use crate::UserAgent;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
|
||||
pub struct User {
|
||||
pub id: Ulid,
|
||||
@@ -81,7 +79,7 @@ pub enum AuthenticationMethod {
|
||||
pub struct UserRecoverySession {
|
||||
pub id: Ulid,
|
||||
pub email: String,
|
||||
pub user_agent: UserAgent,
|
||||
pub user_agent: String,
|
||||
pub ip_address: Option<IpAddr>,
|
||||
pub locale: String,
|
||||
pub created_at: DateTime<Utc>,
|
||||
@@ -137,7 +135,7 @@ pub struct BrowserSession {
|
||||
pub user: User,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub finished_at: Option<DateTime<Utc>>,
|
||||
pub user_agent: Option<UserAgent>,
|
||||
pub user_agent: Option<String>,
|
||||
pub last_active_at: Option<DateTime<Utc>>,
|
||||
pub last_active_ip: Option<IpAddr>,
|
||||
}
|
||||
@@ -159,9 +157,9 @@ impl BrowserSession {
|
||||
user,
|
||||
created_at: now,
|
||||
finished_at: None,
|
||||
user_agent: Some(UserAgent::parse(
|
||||
user_agent: Some(
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Safari/537.36".to_owned()
|
||||
)),
|
||||
),
|
||||
last_active_at: Some(now),
|
||||
last_active_ip: None,
|
||||
})
|
||||
@@ -213,7 +211,7 @@ pub struct UserRegistration {
|
||||
pub password: Option<UserRegistrationPassword>,
|
||||
pub post_auth_action: Option<serde_json::Value>,
|
||||
pub ip_address: Option<IpAddr>,
|
||||
pub user_agent: Option<UserAgent>,
|
||||
pub user_agent: Option<String>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub completed_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ impl
|
||||
user_session_id: session.user_session_id,
|
||||
redirect_uri: sso_login.map(|sso| sso.redirect_uri),
|
||||
created_at: session.created_at,
|
||||
user_agent: session.user_agent.map(|ua| ua.raw),
|
||||
user_agent: session.user_agent,
|
||||
last_active_at: session.last_active_at,
|
||||
last_active_ip: session.last_active_ip,
|
||||
finished_at,
|
||||
@@ -313,7 +313,7 @@ impl From<mas_data_model::Session> for OAuth2Session {
|
||||
user_session_id: session.user_session_id,
|
||||
client_id: session.client_id,
|
||||
scope: session.scope.to_string(),
|
||||
user_agent: session.user_agent.map(|ua| ua.raw),
|
||||
user_agent: session.user_agent,
|
||||
last_active_at: session.last_active_at,
|
||||
last_active_ip: session.last_active_ip,
|
||||
}
|
||||
@@ -406,7 +406,7 @@ impl From<mas_data_model::BrowserSession> for UserSession {
|
||||
created_at: value.created_at,
|
||||
finished_at: value.finished_at,
|
||||
user_id: value.user.id,
|
||||
user_agent: value.user_agent.map(|ua| ua.raw),
|
||||
user_agent: value.user_agent,
|
||||
last_active_at: value.last_active_at,
|
||||
last_active_ip: value.last_active_ip,
|
||||
}
|
||||
|
||||
@@ -11,9 +11,7 @@ use axum_extra::typed_header::TypedHeader;
|
||||
use chrono::Duration;
|
||||
use hyper::StatusCode;
|
||||
use mas_axum_utils::record_error;
|
||||
use mas_data_model::{
|
||||
CompatSession, CompatSsoLoginState, Device, SiteConfig, TokenType, User, UserAgent,
|
||||
};
|
||||
use mas_data_model::{CompatSession, CompatSsoLoginState, Device, SiteConfig, TokenType, User};
|
||||
use mas_matrix::HomeserverConnection;
|
||||
use mas_storage::{
|
||||
BoxClock, BoxRepository, BoxRng, Clock, RepositoryAccess,
|
||||
@@ -276,7 +274,7 @@ pub(crate) async fn post(
|
||||
user_agent: Option<TypedHeader<headers::UserAgent>>,
|
||||
MatrixJsonBody(input): MatrixJsonBody<RequestBody>,
|
||||
) -> Result<impl IntoResponse, RouteError> {
|
||||
let user_agent = user_agent.map(|ua| UserAgent::parse(ua.as_str().to_owned()));
|
||||
let user_agent = user_agent.map(|ua| ua.as_str().to_owned());
|
||||
let login_type = input.credentials.login_type();
|
||||
let (mut session, user) = match (password_manager.is_enabled(), input.credentials) {
|
||||
(
|
||||
|
||||
@@ -81,7 +81,11 @@ impl BrowserSession {
|
||||
|
||||
/// The user-agent with which the session was created.
|
||||
pub async fn user_agent(&self) -> Option<UserAgent> {
|
||||
self.0.user_agent.clone().map(UserAgent::from)
|
||||
self.0
|
||||
.user_agent
|
||||
.clone()
|
||||
.map(mas_data_model::UserAgent::parse)
|
||||
.map(UserAgent::from)
|
||||
}
|
||||
|
||||
/// The last IP address used by the session.
|
||||
|
||||
@@ -98,7 +98,11 @@ impl CompatSession {
|
||||
|
||||
/// The user-agent with which the session was created.
|
||||
pub async fn user_agent(&self) -> Option<UserAgent> {
|
||||
self.session.user_agent.clone().map(UserAgent::from)
|
||||
self.session
|
||||
.user_agent
|
||||
.clone()
|
||||
.map(mas_data_model::UserAgent::parse)
|
||||
.map(UserAgent::from)
|
||||
}
|
||||
|
||||
/// The associated SSO login, if any.
|
||||
|
||||
@@ -61,7 +61,11 @@ impl OAuth2Session {
|
||||
|
||||
/// The user-agent with which the session was created.
|
||||
pub async fn user_agent(&self) -> Option<UserAgent> {
|
||||
self.0.user_agent.clone().map(UserAgent::from)
|
||||
self.0
|
||||
.user_agent
|
||||
.clone()
|
||||
.map(mas_data_model::UserAgent::parse)
|
||||
.map(UserAgent::from)
|
||||
}
|
||||
|
||||
/// The state of the session.
|
||||
|
||||
@@ -13,7 +13,6 @@ use mas_axum_utils::{
|
||||
client_authorization::{ClientAuthorization, CredentialsVerificationError},
|
||||
record_error,
|
||||
};
|
||||
use mas_data_model::UserAgent;
|
||||
use mas_keystore::Encrypter;
|
||||
use mas_router::UrlBuilder;
|
||||
use mas_storage::{BoxClock, BoxRepository, BoxRng, oauth2::OAuth2DeviceCodeGrantParams};
|
||||
@@ -137,7 +136,7 @@ pub(crate) async fn post(
|
||||
|
||||
let expires_in = Duration::microseconds(20 * 60 * 1000 * 1000);
|
||||
|
||||
let user_agent = user_agent.map(|ua| UserAgent::parse(ua.as_str().to_owned()));
|
||||
let user_agent = user_agent.map(|ua| ua.as_str().to_owned());
|
||||
let ip_address = activity_tracker.ip();
|
||||
|
||||
let device_code = Alphanumeric.sample_string(&mut rng, 32);
|
||||
|
||||
@@ -16,7 +16,7 @@ use mas_axum_utils::{
|
||||
record_error,
|
||||
};
|
||||
use mas_data_model::{
|
||||
AuthorizationGrantStage, Client, Device, DeviceCodeGrantState, SiteConfig, TokenType, UserAgent,
|
||||
AuthorizationGrantStage, Client, Device, DeviceCodeGrantState, SiteConfig, TokenType,
|
||||
};
|
||||
use mas_keystore::{Encrypter, Keystore};
|
||||
use mas_matrix::HomeserverConnection;
|
||||
@@ -285,7 +285,7 @@ pub(crate) async fn post(
|
||||
user_agent: Option<TypedHeader<headers::UserAgent>>,
|
||||
client_authorization: ClientAuthorization<AccessTokenRequest>,
|
||||
) -> Result<impl IntoResponse, RouteError> {
|
||||
let user_agent = user_agent.map(|ua| UserAgent::parse(ua.as_str().to_owned()));
|
||||
let user_agent = user_agent.map(|ua| ua.as_str().to_owned());
|
||||
let client = client_authorization
|
||||
.credentials
|
||||
.fetch(&mut repo)
|
||||
@@ -415,7 +415,7 @@ async fn authorization_code_grant(
|
||||
site_config: &SiteConfig,
|
||||
mut repo: BoxRepository,
|
||||
homeserver: &Arc<dyn HomeserverConnection>,
|
||||
user_agent: Option<UserAgent>,
|
||||
user_agent: Option<String>,
|
||||
) -> Result<(AccessTokenResponse, BoxRepository), RouteError> {
|
||||
// Check that the client is allowed to use this grant type
|
||||
if !client.grant_types.contains(&GrantType::AuthorizationCode) {
|
||||
@@ -596,7 +596,7 @@ async fn refresh_token_grant(
|
||||
client: &Client,
|
||||
site_config: &SiteConfig,
|
||||
mut repo: BoxRepository,
|
||||
user_agent: Option<UserAgent>,
|
||||
user_agent: Option<String>,
|
||||
) -> Result<(AccessTokenResponse, BoxRepository), RouteError> {
|
||||
// Check that the client is allowed to use this grant type
|
||||
if !client.grant_types.contains(&GrantType::RefreshToken) {
|
||||
@@ -749,7 +749,7 @@ async fn client_credentials_grant(
|
||||
site_config: &SiteConfig,
|
||||
mut repo: BoxRepository,
|
||||
mut policy: Policy,
|
||||
user_agent: Option<UserAgent>,
|
||||
user_agent: Option<String>,
|
||||
) -> Result<(AccessTokenResponse, BoxRepository), RouteError> {
|
||||
// Check that the client is allowed to use this grant type
|
||||
if !client.grant_types.contains(&GrantType::ClientCredentials) {
|
||||
@@ -771,7 +771,7 @@ async fn client_credentials_grant(
|
||||
grant_type: mas_policy::GrantType::ClientCredentials,
|
||||
requester: mas_policy::Requester {
|
||||
ip_address: activity_tracker.ip(),
|
||||
user_agent: user_agent.clone().map(|ua| ua.raw),
|
||||
user_agent: user_agent.clone(),
|
||||
},
|
||||
})
|
||||
.await?;
|
||||
@@ -828,7 +828,7 @@ async fn device_code_grant(
|
||||
site_config: &SiteConfig,
|
||||
mut repo: BoxRepository,
|
||||
homeserver: &Arc<dyn HomeserverConnection>,
|
||||
user_agent: Option<UserAgent>,
|
||||
user_agent: Option<String>,
|
||||
) -> Result<(AccessTokenResponse, BoxRepository), RouteError> {
|
||||
// Check that the client is allowed to use this grant type
|
||||
if !client.grant_types.contains(&GrantType::DeviceCode) {
|
||||
|
||||
@@ -19,7 +19,6 @@ use mas_axum_utils::{
|
||||
csrf::{CsrfExt, ProtectedForm},
|
||||
record_error,
|
||||
};
|
||||
use mas_data_model::UserAgent;
|
||||
use mas_jose::jwt::Jwt;
|
||||
use mas_matrix::HomeserverConnection;
|
||||
use mas_policy::Policy;
|
||||
@@ -233,7 +232,7 @@ pub(crate) async fn get(
|
||||
user_agent: Option<TypedHeader<headers::UserAgent>>,
|
||||
Path(link_id): Path<Ulid>,
|
||||
) -> Result<impl IntoResponse, RouteError> {
|
||||
let user_agent = user_agent.map(|ua| UserAgent::parse(ua.as_str().to_owned()));
|
||||
let user_agent = user_agent.map(|ua| ua.as_str().to_owned());
|
||||
let sessions_cookie = UpstreamSessionsCookie::load(&cookie_jar);
|
||||
let (session_id, post_auth_action) = sessions_cookie
|
||||
.lookup_link(link_id)
|
||||
@@ -502,7 +501,7 @@ pub(crate) async fn get(
|
||||
email: None,
|
||||
requester: mas_policy::Requester {
|
||||
ip_address: activity_tracker.ip(),
|
||||
user_agent: user_agent.clone().map(|ua| ua.raw),
|
||||
user_agent: user_agent.clone(),
|
||||
},
|
||||
})
|
||||
.await?;
|
||||
@@ -568,7 +567,7 @@ pub(crate) async fn post(
|
||||
Path(link_id): Path<Ulid>,
|
||||
Form(form): Form<ProtectedForm<FormData>>,
|
||||
) -> Result<Response, RouteError> {
|
||||
let user_agent = user_agent.map(|ua| UserAgent::parse(ua.as_str().to_owned()));
|
||||
let user_agent = user_agent.map(|ua| ua.as_str().to_owned());
|
||||
let form = cookie_jar.verify_form(&clock, form)?;
|
||||
|
||||
let sessions_cookie = UpstreamSessionsCookie::load(&cookie_jar);
|
||||
@@ -786,7 +785,7 @@ pub(crate) async fn post(
|
||||
email: email.as_deref(),
|
||||
requester: mas_policy::Requester {
|
||||
ip_address: activity_tracker.ip(),
|
||||
user_agent: user_agent.clone().map(|ua| ua.raw),
|
||||
user_agent: user_agent.clone(),
|
||||
},
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -17,7 +17,7 @@ use mas_axum_utils::{
|
||||
cookies::CookieJar,
|
||||
csrf::{CsrfExt, ProtectedForm},
|
||||
};
|
||||
use mas_data_model::{UserAgent, oauth2::LoginHint};
|
||||
use mas_data_model::oauth2::LoginHint;
|
||||
use mas_i18n::DataLocale;
|
||||
use mas_matrix::HomeserverConnection;
|
||||
use mas_router::{UpstreamOAuth2Authorize, UrlBuilder};
|
||||
@@ -146,7 +146,7 @@ pub(crate) async fn post(
|
||||
user_agent: Option<TypedHeader<headers::UserAgent>>,
|
||||
Form(form): Form<ProtectedForm<LoginForm>>,
|
||||
) -> Result<Response, FancyError> {
|
||||
let user_agent = user_agent.map(|ua| UserAgent::parse(ua.as_str().to_owned()));
|
||||
let user_agent = user_agent.map(|ua| ua.as_str().to_owned());
|
||||
if !site_config.password_login_enabled {
|
||||
// XXX: is it necessary to have better errors here?
|
||||
return Ok(StatusCode::METHOD_NOT_ALLOWED.into_response());
|
||||
|
||||
@@ -18,7 +18,7 @@ use mas_axum_utils::{
|
||||
cookies::CookieJar,
|
||||
csrf::{CsrfExt, ProtectedForm},
|
||||
};
|
||||
use mas_data_model::{SiteConfig, UserAgent};
|
||||
use mas_data_model::SiteConfig;
|
||||
use mas_router::UrlBuilder;
|
||||
use mas_storage::{
|
||||
BoxClock, BoxRepository, BoxRng,
|
||||
@@ -102,7 +102,7 @@ pub(crate) async fn post(
|
||||
return Ok((cookie_jar, url_builder.redirect(&mas_router::Index)).into_response());
|
||||
}
|
||||
|
||||
let user_agent = UserAgent::parse(user_agent.as_str().to_owned());
|
||||
let user_agent = user_agent.as_str().to_owned();
|
||||
let ip_address = activity_tracker.ip();
|
||||
|
||||
let form = cookie_jar.verify_form(&clock, form)?;
|
||||
|
||||
@@ -18,7 +18,7 @@ use mas_axum_utils::{
|
||||
cookies::CookieJar,
|
||||
csrf::{CsrfExt, CsrfToken, ProtectedForm},
|
||||
};
|
||||
use mas_data_model::{CaptchaConfig, UserAgent};
|
||||
use mas_data_model::CaptchaConfig;
|
||||
use mas_i18n::DataLocale;
|
||||
use mas_matrix::HomeserverConnection;
|
||||
use mas_policy::Policy;
|
||||
@@ -141,7 +141,7 @@ pub(crate) async fn post(
|
||||
cookie_jar: CookieJar,
|
||||
Form(form): Form<ProtectedForm<RegisterForm>>,
|
||||
) -> Result<Response, FancyError> {
|
||||
let user_agent = user_agent.map(|ua| UserAgent::parse(ua.as_str().to_owned()));
|
||||
let user_agent = user_agent.map(|ua| ua.as_str().to_owned());
|
||||
|
||||
let ip_address = activity_tracker.ip();
|
||||
if !site_config.password_registration_enabled {
|
||||
@@ -239,7 +239,7 @@ pub(crate) async fn post(
|
||||
email: Some(&form.email),
|
||||
requester: mas_policy::Requester {
|
||||
ip_address: activity_tracker.ip(),
|
||||
user_agent: user_agent.clone().map(|ua| ua.raw),
|
||||
user_agent: user_agent.clone(),
|
||||
},
|
||||
})
|
||||
.await?;
|
||||
|
||||
@@ -13,7 +13,6 @@ use axum::{
|
||||
use axum_extra::TypedHeader;
|
||||
use chrono::Duration;
|
||||
use mas_axum_utils::{FancyError, SessionInfoExt as _, cookies::CookieJar};
|
||||
use mas_data_model::UserAgent;
|
||||
use mas_matrix::HomeserverConnection;
|
||||
use mas_router::{PostAuthAction, UrlBuilder};
|
||||
use mas_storage::{
|
||||
@@ -56,7 +55,7 @@ pub(crate) async fn get(
|
||||
cookie_jar: CookieJar,
|
||||
Path(id): Path<Ulid>,
|
||||
) -> Result<Response, FancyError> {
|
||||
let user_agent = user_agent.map(|ua| UserAgent::parse(ua.as_str().to_owned()));
|
||||
let user_agent = user_agent.map(|ua| ua.as_str().to_owned());
|
||||
let registration = repo
|
||||
.user_registration()
|
||||
.lookup(id)
|
||||
|
||||
@@ -7,9 +7,7 @@
|
||||
//! A module containing PostgreSQL implementation of repositories for sessions
|
||||
|
||||
use async_trait::async_trait;
|
||||
use mas_data_model::{
|
||||
CompatSession, CompatSessionState, Device, Session, SessionState, User, UserAgent,
|
||||
};
|
||||
use mas_data_model::{CompatSession, CompatSessionState, Device, Session, SessionState, User};
|
||||
use mas_storage::{
|
||||
Clock, Page, Pagination,
|
||||
app_session::{AppSession, AppSessionFilter, AppSessionRepository, AppSessionState},
|
||||
@@ -106,7 +104,6 @@ impl TryFrom<AppSessionLookup> for AppSession {
|
||||
last_active_ip,
|
||||
} = value;
|
||||
|
||||
let user_agent = user_agent.map(UserAgent::parse);
|
||||
let user_session_id = user_session_id.map(Ulid::from);
|
||||
|
||||
match (
|
||||
|
||||
@@ -20,7 +20,7 @@ pub use self::{
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use chrono::Duration;
|
||||
use mas_data_model::{Device, UserAgent};
|
||||
use mas_data_model::Device;
|
||||
use mas_storage::{
|
||||
Clock, Pagination, RepositoryAccess,
|
||||
clock::MockClock,
|
||||
@@ -125,7 +125,7 @@ mod tests {
|
||||
assert!(session_lookup.user_agent.is_none());
|
||||
let session = repo
|
||||
.compat_session()
|
||||
.record_user_agent(session_lookup, UserAgent::parse("Mozilla/5.0".to_owned()))
|
||||
.record_user_agent(session_lookup, "Mozilla/5.0".to_owned())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(session.user_agent.as_deref(), Some("Mozilla/5.0"));
|
||||
|
||||
@@ -10,7 +10,7 @@ use async_trait::async_trait;
|
||||
use chrono::{DateTime, Utc};
|
||||
use mas_data_model::{
|
||||
BrowserSession, CompatSession, CompatSessionState, CompatSsoLogin, CompatSsoLoginState, Device,
|
||||
User, UserAgent,
|
||||
User,
|
||||
};
|
||||
use mas_storage::{
|
||||
Clock, Page, Pagination,
|
||||
@@ -77,7 +77,7 @@ impl From<CompatSessionLookup> for CompatSession {
|
||||
human_name: value.human_name,
|
||||
created_at: value.created_at,
|
||||
is_synapse_admin: value.is_synapse_admin,
|
||||
user_agent: value.user_agent.map(UserAgent::parse),
|
||||
user_agent: value.user_agent,
|
||||
last_active_at: value.last_active_at,
|
||||
last_active_ip: value.last_active_ip,
|
||||
}
|
||||
@@ -126,7 +126,7 @@ impl TryFrom<CompatSessionAndSsoLoginLookup> for (CompatSession, Option<CompatSs
|
||||
user_session_id: value.user_session_id.map(Ulid::from),
|
||||
created_at: value.created_at,
|
||||
is_synapse_admin: value.is_synapse_admin,
|
||||
user_agent: value.user_agent.map(UserAgent::parse),
|
||||
user_agent: value.user_agent,
|
||||
last_active_at: value.last_active_at,
|
||||
last_active_ip: value.last_active_ip,
|
||||
};
|
||||
@@ -598,7 +598,7 @@ impl CompatSessionRepository for PgCompatSessionRepository<'_> {
|
||||
async fn record_user_agent(
|
||||
&mut self,
|
||||
mut compat_session: CompatSession,
|
||||
user_agent: UserAgent,
|
||||
user_agent: String,
|
||||
) -> Result<CompatSession, Self::Error> {
|
||||
let res = sqlx::query!(
|
||||
r#"
|
||||
|
||||
@@ -8,7 +8,7 @@ use std::net::IpAddr;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use chrono::{DateTime, Utc};
|
||||
use mas_data_model::{BrowserSession, DeviceCodeGrant, DeviceCodeGrantState, Session, UserAgent};
|
||||
use mas_data_model::{BrowserSession, DeviceCodeGrant, DeviceCodeGrantState, Session};
|
||||
use mas_storage::{
|
||||
Clock,
|
||||
oauth2::{OAuth2DeviceCodeGrantParams, OAuth2DeviceCodeGrantRepository},
|
||||
@@ -132,7 +132,7 @@ impl TryFrom<OAuth2DeviceGrantLookup> for DeviceCodeGrant {
|
||||
created_at,
|
||||
expires_at,
|
||||
ip_address,
|
||||
user_agent: user_agent.map(UserAgent::parse),
|
||||
user_agent,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ pub use self::{
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use chrono::Duration;
|
||||
use mas_data_model::{AuthorizationCode, UserAgent};
|
||||
use mas_data_model::AuthorizationCode;
|
||||
use mas_storage::{
|
||||
Clock, Pagination,
|
||||
clock::MockClock,
|
||||
@@ -351,7 +351,7 @@ mod tests {
|
||||
assert!(session.user_agent.is_none());
|
||||
let session = repo
|
||||
.oauth2_session()
|
||||
.record_user_agent(session, UserAgent::parse("Mozilla/5.0".to_owned()))
|
||||
.record_user_agent(session, "Mozilla/5.0".to_owned())
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(session.user_agent.as_deref(), Some("Mozilla/5.0"));
|
||||
|
||||
@@ -8,7 +8,7 @@ use std::net::IpAddr;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use chrono::{DateTime, Utc};
|
||||
use mas_data_model::{BrowserSession, Client, Session, SessionState, User, UserAgent};
|
||||
use mas_data_model::{BrowserSession, Client, Session, SessionState, User};
|
||||
use mas_storage::{
|
||||
Clock, Page, Pagination,
|
||||
oauth2::{OAuth2SessionFilter, OAuth2SessionRepository},
|
||||
@@ -87,7 +87,7 @@ impl TryFrom<OAuthSessionLookup> for Session {
|
||||
user_id: value.user_id.map(Ulid::from),
|
||||
user_session_id: value.user_session_id.map(Ulid::from),
|
||||
scope,
|
||||
user_agent: value.user_agent.map(UserAgent::parse),
|
||||
user_agent: value.user_agent,
|
||||
last_active_at: value.last_active_at,
|
||||
last_active_ip: value.last_active_ip,
|
||||
})
|
||||
@@ -490,14 +490,14 @@ impl OAuth2SessionRepository for PgOAuth2SessionRepository<'_> {
|
||||
%session.id,
|
||||
%session.scope,
|
||||
client.id = %session.client_id,
|
||||
session.user_agent = %user_agent.raw,
|
||||
session.user_agent = user_agent,
|
||||
),
|
||||
err,
|
||||
)]
|
||||
async fn record_user_agent(
|
||||
&mut self,
|
||||
mut session: Session,
|
||||
user_agent: UserAgent,
|
||||
user_agent: String,
|
||||
) -> Result<Session, Self::Error> {
|
||||
let res = sqlx::query!(
|
||||
r#"
|
||||
|
||||
@@ -8,7 +8,7 @@ use std::net::IpAddr;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use chrono::{DateTime, Duration, Utc};
|
||||
use mas_data_model::{UserAgent, UserEmail, UserRecoverySession, UserRecoveryTicket};
|
||||
use mas_data_model::{UserEmail, UserRecoverySession, UserRecoveryTicket};
|
||||
use mas_storage::{Clock, user::UserRecoveryRepository};
|
||||
use rand::RngCore;
|
||||
use sqlx::PgConnection;
|
||||
@@ -45,7 +45,7 @@ impl From<UserRecoverySessionRow> for UserRecoverySession {
|
||||
UserRecoverySession {
|
||||
id: row.user_recovery_session_id.into(),
|
||||
email: row.email,
|
||||
user_agent: UserAgent::parse(row.user_agent),
|
||||
user_agent: row.user_agent,
|
||||
ip_address: row.ip_address,
|
||||
locale: row.locale,
|
||||
created_at: row.created_at,
|
||||
@@ -127,7 +127,7 @@ impl UserRecoveryRepository for PgUserRecoveryRepository<'_> {
|
||||
db.query.text,
|
||||
user_recovery_session.id,
|
||||
user_recovery_session.email = email,
|
||||
user_recovery_session.user_agent = &*user_agent,
|
||||
user_recovery_session.user_agent = user_agent,
|
||||
user_recovery_session.ip_address = ip_address.map(|ip| ip.to_string()),
|
||||
)
|
||||
)]
|
||||
@@ -136,7 +136,7 @@ impl UserRecoveryRepository for PgUserRecoveryRepository<'_> {
|
||||
rng: &mut (dyn RngCore + Send),
|
||||
clock: &dyn Clock,
|
||||
email: String,
|
||||
user_agent: UserAgent,
|
||||
user_agent: String,
|
||||
ip_address: Option<IpAddr>,
|
||||
locale: String,
|
||||
) -> Result<UserRecoverySession, Self::Error> {
|
||||
|
||||
@@ -7,9 +7,7 @@ use std::net::IpAddr;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use chrono::{DateTime, Utc};
|
||||
use mas_data_model::{
|
||||
UserAgent, UserEmailAuthentication, UserRegistration, UserRegistrationPassword,
|
||||
};
|
||||
use mas_data_model::{UserEmailAuthentication, UserRegistration, UserRegistrationPassword};
|
||||
use mas_storage::{Clock, user::UserRegistrationRepository};
|
||||
use rand::RngCore;
|
||||
use sqlx::PgConnection;
|
||||
@@ -53,7 +51,6 @@ impl TryFrom<UserRegistrationLookup> for UserRegistration {
|
||||
|
||||
fn try_from(value: UserRegistrationLookup) -> Result<Self, Self::Error> {
|
||||
let id = Ulid::from(value.user_registration_id);
|
||||
let user_agent = value.user_agent.map(UserAgent::parse);
|
||||
|
||||
let password = match (value.hashed_password, value.hashed_password_version) {
|
||||
(Some(hashed_password), Some(version)) => {
|
||||
@@ -91,7 +88,7 @@ impl TryFrom<UserRegistrationLookup> for UserRegistration {
|
||||
Ok(UserRegistration {
|
||||
id,
|
||||
ip_address: value.ip_address,
|
||||
user_agent,
|
||||
user_agent: value.user_agent,
|
||||
post_auth_action: value.post_auth_action,
|
||||
username: value.username,
|
||||
display_name: value.display_name,
|
||||
@@ -162,7 +159,7 @@ impl UserRegistrationRepository for PgUserRegistrationRepository<'_> {
|
||||
clock: &dyn Clock,
|
||||
username: String,
|
||||
ip_address: Option<IpAddr>,
|
||||
user_agent: Option<UserAgent>,
|
||||
user_agent: Option<String>,
|
||||
post_auth_action: Option<serde_json::Value>,
|
||||
) -> Result<UserRegistration, Self::Error> {
|
||||
let created_at = clock.now();
|
||||
@@ -394,7 +391,7 @@ impl UserRegistrationRepository for PgUserRegistrationRepository<'_> {
|
||||
mod tests {
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
|
||||
use mas_data_model::{UserAgent, UserRegistrationPassword};
|
||||
use mas_data_model::UserRegistrationPassword;
|
||||
use mas_storage::{Clock, clock::MockClock};
|
||||
use rand::SeedableRng;
|
||||
use rand_chacha::ChaChaRng;
|
||||
@@ -487,16 +484,13 @@ mod tests {
|
||||
&clock,
|
||||
"alice".to_owned(),
|
||||
Some(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))),
|
||||
Some(UserAgent::parse("Mozilla/5.0".to_owned())),
|
||||
Some("Mozilla/5.0".to_owned()),
|
||||
Some(serde_json::json!({"action": "continue_compat_sso_login", "id": "01FSHN9AG0MKGTBNZ16RDR3PVY"})),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
registration.user_agent,
|
||||
Some(UserAgent::parse("Mozilla/5.0".to_owned()))
|
||||
);
|
||||
assert_eq!(registration.user_agent, Some("Mozilla/5.0".to_owned()));
|
||||
assert_eq!(
|
||||
registration.ip_address,
|
||||
Some(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)))
|
||||
|
||||
@@ -10,7 +10,7 @@ use async_trait::async_trait;
|
||||
use chrono::{DateTime, Utc};
|
||||
use mas_data_model::{
|
||||
Authentication, AuthenticationMethod, BrowserSession, Password,
|
||||
UpstreamOAuthAuthorizationSession, User, UserAgent,
|
||||
UpstreamOAuthAuthorizationSession, User,
|
||||
};
|
||||
use mas_storage::{
|
||||
Clock, Page, Pagination,
|
||||
@@ -83,7 +83,7 @@ impl TryFrom<SessionLookup> for BrowserSession {
|
||||
user,
|
||||
created_at: value.user_session_created_at,
|
||||
finished_at: value.user_session_finished_at,
|
||||
user_agent: value.user_session_user_agent.map(UserAgent::parse),
|
||||
user_agent: value.user_session_user_agent,
|
||||
last_active_at: value.user_session_last_active_at,
|
||||
last_active_ip: value.user_session_last_active_ip,
|
||||
})
|
||||
@@ -208,7 +208,7 @@ impl BrowserSessionRepository for PgBrowserSessionRepository<'_> {
|
||||
rng: &mut (dyn RngCore + Send),
|
||||
clock: &dyn Clock,
|
||||
user: &User,
|
||||
user_agent: Option<UserAgent>,
|
||||
user_agent: Option<String>,
|
||||
) -> Result<BrowserSession, Self::Error> {
|
||||
let created_at = clock.now();
|
||||
let id = Ulid::from_datetime_with_source(created_at.into(), rng);
|
||||
|
||||
@@ -8,7 +8,7 @@ use std::net::IpAddr;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use chrono::{DateTime, Utc};
|
||||
use mas_data_model::{BrowserSession, CompatSession, CompatSsoLogin, Device, User, UserAgent};
|
||||
use mas_data_model::{BrowserSession, CompatSession, CompatSsoLogin, Device, User};
|
||||
use rand_core::RngCore;
|
||||
use ulid::Ulid;
|
||||
|
||||
@@ -322,7 +322,7 @@ pub trait CompatSessionRepository: Send + Sync {
|
||||
async fn record_user_agent(
|
||||
&mut self,
|
||||
compat_session: CompatSession,
|
||||
user_agent: UserAgent,
|
||||
user_agent: String,
|
||||
) -> Result<CompatSession, Self::Error>;
|
||||
}
|
||||
|
||||
@@ -367,6 +367,6 @@ repository_impl!(CompatSessionRepository:
|
||||
async fn record_user_agent(
|
||||
&mut self,
|
||||
compat_session: CompatSession,
|
||||
user_agent: UserAgent,
|
||||
user_agent: String,
|
||||
) -> Result<CompatSession, Self::Error>;
|
||||
);
|
||||
|
||||
@@ -8,7 +8,7 @@ use std::net::IpAddr;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use chrono::Duration;
|
||||
use mas_data_model::{BrowserSession, Client, DeviceCodeGrant, Session, UserAgent};
|
||||
use mas_data_model::{BrowserSession, Client, DeviceCodeGrant, Session};
|
||||
use oauth2_types::scope::Scope;
|
||||
use rand_core::RngCore;
|
||||
use ulid::Ulid;
|
||||
@@ -36,7 +36,7 @@ pub struct OAuth2DeviceCodeGrantParams<'a> {
|
||||
pub ip_address: Option<IpAddr>,
|
||||
|
||||
/// The user agent from which the request was made
|
||||
pub user_agent: Option<UserAgent>,
|
||||
pub user_agent: Option<String>,
|
||||
}
|
||||
|
||||
/// An [`OAuth2DeviceCodeGrantRepository`] helps interacting with
|
||||
|
||||
@@ -8,7 +8,7 @@ use std::net::IpAddr;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use chrono::{DateTime, Utc};
|
||||
use mas_data_model::{BrowserSession, Client, Device, Session, User, UserAgent};
|
||||
use mas_data_model::{BrowserSession, Client, Device, Session, User};
|
||||
use oauth2_types::scope::Scope;
|
||||
use rand_core::RngCore;
|
||||
use ulid::Ulid;
|
||||
@@ -428,7 +428,7 @@ pub trait OAuth2SessionRepository: Send + Sync {
|
||||
async fn record_user_agent(
|
||||
&mut self,
|
||||
session: Session,
|
||||
user_agent: UserAgent,
|
||||
user_agent: String,
|
||||
) -> Result<Session, Self::Error>;
|
||||
}
|
||||
|
||||
@@ -487,6 +487,6 @@ repository_impl!(OAuth2SessionRepository:
|
||||
async fn record_user_agent(
|
||||
&mut self,
|
||||
session: Session,
|
||||
user_agent: UserAgent,
|
||||
user_agent: String,
|
||||
) -> Result<Session, Self::Error>;
|
||||
);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
use std::net::IpAddr;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use mas_data_model::{UserAgent, UserEmail, UserRecoverySession, UserRecoveryTicket};
|
||||
use mas_data_model::{UserEmail, UserRecoverySession, UserRecoveryTicket};
|
||||
use rand_core::RngCore;
|
||||
use ulid::Ulid;
|
||||
|
||||
@@ -59,7 +59,7 @@ pub trait UserRecoveryRepository: Send + Sync {
|
||||
rng: &mut (dyn RngCore + Send),
|
||||
clock: &dyn Clock,
|
||||
email: String,
|
||||
user_agent: UserAgent,
|
||||
user_agent: String,
|
||||
ip_address: Option<IpAddr>,
|
||||
locale: String,
|
||||
) -> Result<UserRecoverySession, Self::Error>;
|
||||
@@ -131,7 +131,7 @@ repository_impl!(UserRecoveryRepository:
|
||||
rng: &mut (dyn RngCore + Send),
|
||||
clock: &dyn Clock,
|
||||
email: String,
|
||||
user_agent: UserAgent,
|
||||
user_agent: String,
|
||||
ip_address: Option<IpAddr>,
|
||||
locale: String,
|
||||
) -> Result<UserRecoverySession, Self::Error>;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
use std::net::IpAddr;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use mas_data_model::{UserAgent, UserEmailAuthentication, UserRegistration};
|
||||
use mas_data_model::{UserEmailAuthentication, UserRegistration};
|
||||
use rand_core::RngCore;
|
||||
use ulid::Ulid;
|
||||
use url::Url;
|
||||
@@ -56,7 +56,7 @@ pub trait UserRegistrationRepository: Send + Sync {
|
||||
clock: &dyn Clock,
|
||||
username: String,
|
||||
ip_address: Option<IpAddr>,
|
||||
user_agent: Option<UserAgent>,
|
||||
user_agent: Option<String>,
|
||||
post_auth_action: Option<serde_json::Value>,
|
||||
) -> Result<UserRegistration, Self::Error>;
|
||||
|
||||
@@ -166,7 +166,7 @@ repository_impl!(UserRegistrationRepository:
|
||||
clock: &dyn Clock,
|
||||
username: String,
|
||||
ip_address: Option<IpAddr>,
|
||||
user_agent: Option<UserAgent>,
|
||||
user_agent: Option<String>,
|
||||
post_auth_action: Option<serde_json::Value>,
|
||||
) -> Result<UserRegistration, Self::Error>;
|
||||
async fn set_display_name(
|
||||
|
||||
@@ -9,7 +9,7 @@ use std::net::IpAddr;
|
||||
use async_trait::async_trait;
|
||||
use chrono::{DateTime, Utc};
|
||||
use mas_data_model::{
|
||||
Authentication, BrowserSession, Password, UpstreamOAuthAuthorizationSession, User, UserAgent,
|
||||
Authentication, BrowserSession, Password, UpstreamOAuthAuthorizationSession, User,
|
||||
};
|
||||
use rand_core::RngCore;
|
||||
use ulid::Ulid;
|
||||
@@ -151,7 +151,7 @@ pub trait BrowserSessionRepository: Send + Sync {
|
||||
rng: &mut (dyn RngCore + Send),
|
||||
clock: &dyn Clock,
|
||||
user: &User,
|
||||
user_agent: Option<UserAgent>,
|
||||
user_agent: Option<String>,
|
||||
) -> Result<BrowserSession, Self::Error>;
|
||||
|
||||
/// Finish a [`BrowserSession`]
|
||||
@@ -296,7 +296,7 @@ repository_impl!(BrowserSessionRepository:
|
||||
rng: &mut (dyn RngCore + Send),
|
||||
clock: &dyn Clock,
|
||||
user: &User,
|
||||
user_agent: Option<UserAgent>,
|
||||
user_agent: Option<String>,
|
||||
) -> Result<BrowserSession, Self::Error>;
|
||||
async fn finish(
|
||||
&mut self,
|
||||
|
||||
@@ -22,7 +22,7 @@ use mas_data_model::{
|
||||
AuthorizationGrant, BrowserSession, Client, CompatSsoLogin, CompatSsoLoginState,
|
||||
DeviceCodeGrant, UpstreamOAuthLink, UpstreamOAuthProvider, UpstreamOAuthProviderClaimsImports,
|
||||
UpstreamOAuthProviderDiscoveryMode, UpstreamOAuthProviderPkceMode,
|
||||
UpstreamOAuthProviderTokenAuthMethod, User, UserAgent, UserEmailAuthentication,
|
||||
UpstreamOAuthProviderTokenAuthMethod, User, UserEmailAuthentication,
|
||||
UserEmailAuthenticationCode, UserRecoverySession, UserRegistration,
|
||||
};
|
||||
use mas_i18n::DataLocale;
|
||||
@@ -808,7 +808,7 @@ impl TemplateContext for EmailRecoveryContext {
|
||||
let session = UserRecoverySession {
|
||||
id: Ulid::from_datetime_with_source(now.into(), rng),
|
||||
email: "hello@example.com".to_owned(),
|
||||
user_agent: UserAgent::parse("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/536.30.1 (KHTML, like Gecko) Version/6.0.5 Safari/536.30.1".to_owned()),
|
||||
user_agent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/536.30.1 (KHTML, like Gecko) Version/6.0.5 Safari/536.30.1".to_owned(),
|
||||
ip_address: Some(IpAddr::from([192_u8, 0, 2, 1])),
|
||||
locale: "en".to_owned(),
|
||||
created_at: now,
|
||||
@@ -1106,7 +1106,7 @@ impl TemplateContext for RecoveryProgressContext {
|
||||
let session = UserRecoverySession {
|
||||
id: Ulid::from_datetime_with_source(now.into(), rng),
|
||||
email: "name@mail.com".to_owned(),
|
||||
user_agent: UserAgent::parse("Mozilla/5.0".to_owned()),
|
||||
user_agent: "Mozilla/5.0".to_owned(),
|
||||
ip_address: None,
|
||||
locale: "en".to_owned(),
|
||||
created_at: now,
|
||||
@@ -1148,7 +1148,7 @@ impl TemplateContext for RecoveryExpiredContext {
|
||||
let session = UserRecoverySession {
|
||||
id: Ulid::from_datetime_with_source(now.into(), rng),
|
||||
email: "name@mail.com".to_owned(),
|
||||
user_agent: UserAgent::parse("Mozilla/5.0".to_owned()),
|
||||
user_agent: "Mozilla/5.0".to_owned(),
|
||||
ip_address: None,
|
||||
locale: "en".to_owned(),
|
||||
created_at: now,
|
||||
@@ -1529,7 +1529,7 @@ impl TemplateContext for DeviceConsentContext {
|
||||
created_at: now - Duration::try_minutes(5).unwrap(),
|
||||
expires_at: now + Duration::try_minutes(25).unwrap(),
|
||||
ip_address: Some(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))),
|
||||
user_agent: Some(UserAgent::parse("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Safari/537.36".to_owned())),
|
||||
user_agent: Some("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.0.0 Safari/537.36".to_owned()),
|
||||
};
|
||||
Self { grant, client }
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user