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
Better data-model for compat sessions & devices
This commit is contained in:
@ -1074,6 +1074,104 @@
|
||||
},
|
||||
"query": "\n INSERT INTO oauth2_sessions\n (user_session_id, oauth2_client_id, scope)\n SELECT\n $1,\n og.oauth2_client_id,\n og.scope\n FROM\n oauth2_authorization_grants og\n WHERE\n og.id = $2\n RETURNING id, created_at\n "
|
||||
},
|
||||
"7d94b7b6ed2f68479adb6247880b32bc378790174a81a05dff50b92e9be15bf8": {
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "compat_access_token_id",
|
||||
"ordinal": 0,
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"name": "compat_access_token",
|
||||
"ordinal": 1,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "compat_access_token_created_at",
|
||||
"ordinal": 2,
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"name": "compat_access_token_expires_after",
|
||||
"ordinal": 3,
|
||||
"type_info": "Int4"
|
||||
},
|
||||
{
|
||||
"name": "compat_session_id",
|
||||
"ordinal": 4,
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"name": "compat_session_created_at",
|
||||
"ordinal": 5,
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"name": "compat_session_deleted_at",
|
||||
"ordinal": 6,
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"name": "compat_session_device_id",
|
||||
"ordinal": 7,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "user_id!",
|
||||
"ordinal": 8,
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"name": "user_username!",
|
||||
"ordinal": 9,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "user_email_id?",
|
||||
"ordinal": 10,
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"name": "user_email?",
|
||||
"ordinal": 11,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "user_email_created_at?",
|
||||
"ordinal": 12,
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"name": "user_email_confirmed_at?",
|
||||
"ordinal": 13,
|
||||
"type_info": "Timestamptz"
|
||||
}
|
||||
],
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
}
|
||||
},
|
||||
"query": "\n SELECT\n ct.id AS \"compat_access_token_id\",\n ct.token AS \"compat_access_token\",\n ct.created_at AS \"compat_access_token_created_at\",\n ct.expires_after AS \"compat_access_token_expires_after\",\n cs.id AS \"compat_session_id\",\n cs.created_at AS \"compat_session_created_at\",\n cs.deleted_at AS \"compat_session_deleted_at\",\n cs.device_id AS \"compat_session_device_id\",\n u.id AS \"user_id!\",\n u.username AS \"user_username!\",\n ue.id AS \"user_email_id?\",\n ue.email AS \"user_email?\",\n ue.created_at AS \"user_email_created_at?\",\n ue.confirmed_at AS \"user_email_confirmed_at?\"\n\n FROM compat_access_tokens ct\n INNER JOIN compat_sessions cs\n ON cs.id = ct.compat_session_id\n INNER JOIN users u\n ON u.id = cs.user_id\n LEFT JOIN user_emails ue\n ON ue.id = u.primary_email_id\n\n WHERE ct.token = $1\n AND cs.deleted_at IS NULL\n "
|
||||
},
|
||||
"7de9cfa6e90ba20f5b298ea387cf13a7e40d0f5b3eb903a80d06fbe33074d596": {
|
||||
"describe": {
|
||||
"columns": [
|
||||
@ -1875,86 +1973,6 @@
|
||||
},
|
||||
"query": "\n SELECT COUNT(*) as \"count!\"\n FROM user_sessions s\n WHERE s.user_id = $1 AND s.active\n "
|
||||
},
|
||||
"eb12b728e0d58f6bba1a20fbc9bd01f3a6cbae7e40961b39eac3b294609edf2f": {
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "compat_access_token_id",
|
||||
"ordinal": 0,
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"name": "compat_access_token",
|
||||
"ordinal": 1,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "compat_access_token_created_at",
|
||||
"ordinal": 2,
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"name": "compat_session_deleted_at",
|
||||
"ordinal": 3,
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"name": "compat_session_device_id",
|
||||
"ordinal": 4,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "user_id!",
|
||||
"ordinal": 5,
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"name": "user_username!",
|
||||
"ordinal": 6,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "user_email_id?",
|
||||
"ordinal": 7,
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"name": "user_email?",
|
||||
"ordinal": 8,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "user_email_created_at?",
|
||||
"ordinal": 9,
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"name": "user_email_confirmed_at?",
|
||||
"ordinal": 10,
|
||||
"type_info": "Timestamptz"
|
||||
}
|
||||
],
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text"
|
||||
]
|
||||
}
|
||||
},
|
||||
"query": "\n SELECT\n ct.id AS \"compat_access_token_id\",\n ct.token AS \"compat_access_token\",\n ct.created_at AS \"compat_access_token_created_at\",\n cs.deleted_at AS \"compat_session_deleted_at\",\n cs.device_id AS \"compat_session_device_id\",\n u.id AS \"user_id!\",\n u.username AS \"user_username!\",\n ue.id AS \"user_email_id?\",\n ue.email AS \"user_email?\",\n ue.created_at AS \"user_email_created_at?\",\n ue.confirmed_at AS \"user_email_confirmed_at?\"\n\n FROM compat_access_tokens ct\n INNER JOIN compat_sessions cs\n ON cs.id = ct.compat_session_id\n INNER JOIN users u\n ON u.id = cs.user_id\n LEFT JOIN user_emails ue\n ON ue.id = u.primary_email_id\n\n WHERE ct.token = $1\n AND cs.deleted_at IS NULL\n "
|
||||
},
|
||||
"ebf73a609e81830b16700d2c315fffa93fd85b2886e29f234d9953b18a9f72b5": {
|
||||
"describe": {
|
||||
"columns": [],
|
||||
|
@ -14,8 +14,8 @@
|
||||
|
||||
use anyhow::Context;
|
||||
use argon2::{Argon2, PasswordHash};
|
||||
use chrono::{DateTime, Utc};
|
||||
use mas_data_model::{CompatAccessToken, User, UserEmail};
|
||||
use chrono::{DateTime, Duration, Utc};
|
||||
use mas_data_model::{CompatAccessToken, CompatSession, Device, User, UserEmail};
|
||||
use sqlx::{Acquire, PgExecutor, Postgres};
|
||||
use thiserror::Error;
|
||||
use tokio::task;
|
||||
@ -28,7 +28,10 @@ use crate::{
|
||||
pub struct CompatAccessTokenLookup {
|
||||
compat_access_token_id: i64,
|
||||
compat_access_token: String,
|
||||
compat_access_token_expires_after: Option<i32>,
|
||||
compat_access_token_created_at: DateTime<Utc>,
|
||||
compat_session_id: i64,
|
||||
compat_session_created_at: DateTime<Utc>,
|
||||
compat_session_deleted_at: Option<DateTime<Utc>>,
|
||||
compat_session_device_id: String,
|
||||
user_id: i64,
|
||||
@ -53,14 +56,14 @@ impl CompatAccessTokenLookupError {
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(executor))]
|
||||
#[tracing::instrument(skip(executor), err)]
|
||||
pub async fn lookup_active_compat_access_token(
|
||||
executor: impl PgExecutor<'_>,
|
||||
token: &str,
|
||||
) -> Result<
|
||||
(
|
||||
CompatAccessToken<PostgresqlBackend>,
|
||||
User<PostgresqlBackend>,
|
||||
CompatSession<PostgresqlBackend>,
|
||||
),
|
||||
CompatAccessTokenLookupError,
|
||||
> {
|
||||
@ -71,6 +74,9 @@ pub async fn lookup_active_compat_access_token(
|
||||
ct.id AS "compat_access_token_id",
|
||||
ct.token AS "compat_access_token",
|
||||
ct.created_at AS "compat_access_token_created_at",
|
||||
ct.expires_after AS "compat_access_token_expires_after",
|
||||
cs.id AS "compat_session_id",
|
||||
cs.created_at AS "compat_session_created_at",
|
||||
cs.deleted_at AS "compat_session_deleted_at",
|
||||
cs.device_id AS "compat_session_device_id",
|
||||
u.id AS "user_id!",
|
||||
@ -101,8 +107,9 @@ pub async fn lookup_active_compat_access_token(
|
||||
data: res.compat_access_token_id,
|
||||
token: res.compat_access_token,
|
||||
created_at: res.compat_access_token_created_at,
|
||||
deleted_at: res.compat_session_deleted_at,
|
||||
device_id: res.compat_session_device_id,
|
||||
expires_after: res
|
||||
.compat_access_token_expires_after
|
||||
.map(|d| Duration::seconds(d.into())),
|
||||
};
|
||||
|
||||
let primary_email = match (
|
||||
@ -128,20 +135,30 @@ pub async fn lookup_active_compat_access_token(
|
||||
primary_email,
|
||||
};
|
||||
|
||||
Ok((token, user))
|
||||
let device = Device::try_from(res.compat_session_device_id).unwrap();
|
||||
|
||||
let session = CompatSession {
|
||||
data: res.compat_session_id,
|
||||
user,
|
||||
device,
|
||||
created_at: res.compat_session_created_at,
|
||||
deleted_at: res.compat_session_deleted_at,
|
||||
};
|
||||
|
||||
Ok((token, session))
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(conn, password, token))]
|
||||
#[tracing::instrument(skip(conn, password, token), err)]
|
||||
pub async fn compat_login(
|
||||
conn: impl Acquire<'_, Database = Postgres>,
|
||||
username: &str,
|
||||
password: &str,
|
||||
device_id: String,
|
||||
device: Device,
|
||||
token: String,
|
||||
) -> Result<
|
||||
(
|
||||
CompatAccessToken<PostgresqlBackend>,
|
||||
User<PostgresqlBackend>,
|
||||
CompatSession<PostgresqlBackend>,
|
||||
),
|
||||
anyhow::Error,
|
||||
> {
|
||||
@ -176,7 +193,7 @@ pub async fn compat_login(
|
||||
.instrument(tracing::info_span!("Verify hashed password"))
|
||||
.await??;
|
||||
|
||||
let session = sqlx::query_as!(
|
||||
let res = sqlx::query_as!(
|
||||
IdAndCreationTime,
|
||||
r#"
|
||||
INSERT INTO compat_sessions (user_id, device_id)
|
||||
@ -184,12 +201,21 @@ pub async fn compat_login(
|
||||
RETURNING id, created_at
|
||||
"#,
|
||||
user.data,
|
||||
device_id,
|
||||
device.as_str(),
|
||||
)
|
||||
.fetch_one(&mut txn)
|
||||
.instrument(tracing::info_span!("Insert compat session"))
|
||||
.await
|
||||
.context("could not insert compat session")?;
|
||||
|
||||
let session = CompatSession {
|
||||
data: res.id,
|
||||
user,
|
||||
device,
|
||||
created_at: res.created_at,
|
||||
deleted_at: None,
|
||||
};
|
||||
|
||||
let res = sqlx::query_as!(
|
||||
IdAndCreationTime,
|
||||
r#"
|
||||
@ -197,10 +223,11 @@ pub async fn compat_login(
|
||||
VALUES ($1, $2)
|
||||
RETURNING id, created_at
|
||||
"#,
|
||||
session.id,
|
||||
session.data,
|
||||
token,
|
||||
)
|
||||
.fetch_one(&mut txn)
|
||||
.instrument(tracing::info_span!("Insert compat access token"))
|
||||
.await
|
||||
.context("could not insert compat access token")?;
|
||||
|
||||
@ -208,15 +235,14 @@ pub async fn compat_login(
|
||||
data: res.id,
|
||||
token,
|
||||
created_at: res.created_at,
|
||||
deleted_at: None,
|
||||
device_id,
|
||||
expires_after: None,
|
||||
};
|
||||
|
||||
txn.commit().await.context("could not commit transaction")?;
|
||||
Ok((token, user))
|
||||
Ok((token, session))
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
#[tracing::instrument(skip_all, err)]
|
||||
pub async fn compat_logout(
|
||||
executor: impl PgExecutor<'_>,
|
||||
token: &str,
|
||||
|
@ -43,6 +43,8 @@ impl StorageBackend for PostgresqlBackend {
|
||||
type BrowserSessionData = i64;
|
||||
type ClientData = i64;
|
||||
type CompatAccessTokenData = i64;
|
||||
type CompatRefreshTokenData = i64;
|
||||
type CompatSessionData = i64;
|
||||
type RefreshTokenData = i64;
|
||||
type SessionData = i64;
|
||||
type UserData = i64;
|
||||
|
Reference in New Issue
Block a user