1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-29 22:01:14 +03:00

Make the last activity timestamp and IP available through the API

This commit is contained in:
Quentin Gliech
2023-09-19 19:25:58 +02:00
parent b85655b944
commit 50558a7319
17 changed files with 2562 additions and 2329 deletions

View File

@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use std::net::IpAddr;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use serde::Serialize; use serde::Serialize;
use ulid::Ulid; use ulid::Ulid;
@ -80,6 +82,8 @@ pub struct CompatSession {
pub device: Device, pub device: Device,
pub created_at: DateTime<Utc>, pub created_at: DateTime<Utc>,
pub is_synapse_admin: bool, pub is_synapse_admin: bool,
pub last_active_at: Option<DateTime<Utc>>,
pub last_active_ip: Option<IpAddr>,
} }
impl std::ops::Deref for CompatSession { impl std::ops::Deref for CompatSession {

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use std::net::IpAddr;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use oauth2_types::scope::Scope; use oauth2_types::scope::Scope;
use serde::Serialize; use serde::Serialize;
@ -73,6 +74,8 @@ pub struct Session {
pub user_session_id: Option<Ulid>, pub user_session_id: Option<Ulid>,
pub client_id: Ulid, pub client_id: Ulid,
pub scope: Scope, pub scope: Scope,
pub last_active_at: Option<DateTime<Utc>>,
pub last_active_ip: Option<IpAddr>,
} }
impl std::ops::Deref for Session { impl std::ops::Deref for Session {

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use std::ops::Deref; use std::{net::IpAddr, ops::Deref};
use chrono::{DateTime, Duration, Utc}; use chrono::{DateTime, Duration, Utc};
use rand::{Rng, SeedableRng}; use rand::{Rng, SeedableRng};
@ -81,6 +81,8 @@ pub struct BrowserSession {
pub created_at: DateTime<Utc>, pub created_at: DateTime<Utc>,
pub finished_at: Option<DateTime<Utc>>, pub finished_at: Option<DateTime<Utc>>,
pub user_agent: Option<String>, pub user_agent: Option<String>,
pub last_active_at: Option<DateTime<Utc>>,
pub last_active_ip: Option<IpAddr>,
} }
impl BrowserSession { impl BrowserSession {
@ -101,6 +103,8 @@ impl BrowserSession {
created_at: now, created_at: now,
finished_at: None, finished_at: None,
user_agent: Some("Mozilla/5.0".to_owned()), user_agent: Some("Mozilla/5.0".to_owned()),
last_active_at: Some(now),
last_active_ip: None,
}) })
.collect() .collect()
} }

View File

@ -92,6 +92,16 @@ impl BrowserSession {
pub async fn user_agent(&self) -> Option<&str> { pub async fn user_agent(&self) -> Option<&str> {
self.0.user_agent.as_deref() self.0.user_agent.as_deref()
} }
/// The last IP address used by the session.
pub async fn last_active_ip(&self) -> Option<String> {
self.0.last_active_ip.map(|ip| ip.to_string())
}
/// The last time the session was active.
pub async fn last_active_at(&self) -> Option<DateTime<Utc>> {
self.0.last_active_at
}
} }
/// An authentication records when a user enter their credential in a browser /// An authentication records when a user enter their credential in a browser

View File

@ -142,6 +142,16 @@ impl CompatSession {
mas_data_model::CompatSessionState::Finished { .. } => CompatSessionState::Finished, mas_data_model::CompatSessionState::Finished { .. } => CompatSessionState::Finished,
} }
} }
/// The last IP address used by the session.
pub async fn last_active_ip(&self) -> Option<String> {
self.session.last_active_ip.map(|ip| ip.to_string())
}
/// The last time the session was active.
pub async fn last_active_at(&self) -> Option<DateTime<Utc>> {
self.session.last_active_at
}
} }
/// A compat SSO login represents a login done through the legacy Matrix login /// A compat SSO login represents a login done through the legacy Matrix login

View File

@ -128,6 +128,16 @@ impl OAuth2Session {
Ok(Some(User(user))) Ok(Some(User(user)))
} }
/// The last IP address used by the session.
pub async fn last_active_ip(&self) -> Option<String> {
self.0.last_active_ip.map(|ip| ip.to_string())
}
/// The last time the session was active.
pub async fn last_active_at(&self) -> Option<DateTime<Utc>> {
self.0.last_active_at
}
} }
/// The application type advertised by the client. /// The application type advertised by the client.

View File

@ -1,6 +1,6 @@
{ {
"db_name": "PostgreSQL", "db_name": "PostgreSQL",
"query": "\n SELECT compat_session_id\n , device_id\n , user_id\n , created_at\n , finished_at\n , is_synapse_admin\n FROM compat_sessions\n WHERE compat_session_id = $1\n ", "query": "\n SELECT compat_session_id\n , device_id\n , user_id\n , created_at\n , finished_at\n , is_synapse_admin\n , last_active_at\n , last_active_ip as \"last_active_ip: IpAddr\"\n FROM compat_sessions\n WHERE compat_session_id = $1\n ",
"describe": { "describe": {
"columns": [ "columns": [
{ {
@ -32,6 +32,16 @@
"ordinal": 5, "ordinal": 5,
"name": "is_synapse_admin", "name": "is_synapse_admin",
"type_info": "Bool" "type_info": "Bool"
},
{
"ordinal": 6,
"name": "last_active_at",
"type_info": "Timestamptz"
},
{
"ordinal": 7,
"name": "last_active_ip: IpAddr",
"type_info": "Inet"
} }
], ],
"parameters": { "parameters": {
@ -45,8 +55,10 @@
false, false,
false, false,
true, true,
false false,
true,
true
] ]
}, },
"hash": "0469c1d3ad11fd96febacad33302709c870ead848d6920cdfdb18912d543488e" "hash": "23c03635d6433099a4353ba0c80b88737724edb16315832891550e29088d02bf"
} }

View File

@ -1,6 +1,6 @@
{ {
"db_name": "PostgreSQL", "db_name": "PostgreSQL",
"query": "\n SELECT s.user_session_id\n , s.created_at AS \"user_session_created_at\"\n , s.finished_at AS \"user_session_finished_at\"\n , s.user_agent AS \"user_session_user_agent\"\n , u.user_id\n , u.username AS \"user_username\"\n , u.primary_user_email_id AS \"user_primary_user_email_id\"\n , u.created_at AS \"user_created_at\"\n , u.locked_at AS \"user_locked_at\"\n FROM user_sessions s\n INNER JOIN users u\n USING (user_id)\n WHERE s.user_session_id = $1\n ", "query": "\n SELECT s.user_session_id\n , s.created_at AS \"user_session_created_at\"\n , s.finished_at AS \"user_session_finished_at\"\n , s.user_agent AS \"user_session_user_agent\"\n , s.last_active_at AS \"user_session_last_active_at\"\n , s.last_active_ip AS \"user_session_last_active_ip: IpAddr\"\n , u.user_id\n , u.username AS \"user_username\"\n , u.primary_user_email_id AS \"user_primary_user_email_id\"\n , u.created_at AS \"user_created_at\"\n , u.locked_at AS \"user_locked_at\"\n FROM user_sessions s\n INNER JOIN users u\n USING (user_id)\n WHERE s.user_session_id = $1\n ",
"describe": { "describe": {
"columns": [ "columns": [
{ {
@ -25,26 +25,36 @@
}, },
{ {
"ordinal": 4, "ordinal": 4,
"name": "user_session_last_active_at",
"type_info": "Timestamptz"
},
{
"ordinal": 5,
"name": "user_session_last_active_ip: IpAddr",
"type_info": "Inet"
},
{
"ordinal": 6,
"name": "user_id", "name": "user_id",
"type_info": "Uuid" "type_info": "Uuid"
}, },
{ {
"ordinal": 5, "ordinal": 7,
"name": "user_username", "name": "user_username",
"type_info": "Text" "type_info": "Text"
}, },
{ {
"ordinal": 6, "ordinal": 8,
"name": "user_primary_user_email_id", "name": "user_primary_user_email_id",
"type_info": "Uuid" "type_info": "Uuid"
}, },
{ {
"ordinal": 7, "ordinal": 9,
"name": "user_created_at", "name": "user_created_at",
"type_info": "Timestamptz" "type_info": "Timestamptz"
}, },
{ {
"ordinal": 8, "ordinal": 10,
"name": "user_locked_at", "name": "user_locked_at",
"type_info": "Timestamptz" "type_info": "Timestamptz"
} }
@ -59,6 +69,8 @@
false, false,
true, true,
true, true,
true,
true,
false, false,
false, false,
true, true,
@ -66,5 +78,5 @@
true true
] ]
}, },
"hash": "b98052065469a71643bb332cbeb07e0e43c620ffa1a592eb45ab326e0064efa8" "hash": "2b0d54c284dc4d946faae4190568bf597c04b40f010132dd7bf68462c47f9eac"
} }

View File

@ -1,6 +1,6 @@
{ {
"db_name": "PostgreSQL", "db_name": "PostgreSQL",
"query": "\n SELECT oauth2_session_id\n , user_id\n , user_session_id\n , oauth2_client_id\n , scope_list\n , created_at\n , finished_at\n FROM oauth2_sessions\n\n WHERE oauth2_session_id = $1\n ", "query": "\n SELECT oauth2_session_id\n , user_id\n , user_session_id\n , oauth2_client_id\n , scope_list\n , created_at\n , finished_at\n , last_active_at\n , last_active_ip as \"last_active_ip: IpAddr\"\n FROM oauth2_sessions\n\n WHERE oauth2_session_id = $1\n ",
"describe": { "describe": {
"columns": [ "columns": [
{ {
@ -37,6 +37,16 @@
"ordinal": 6, "ordinal": 6,
"name": "finished_at", "name": "finished_at",
"type_info": "Timestamptz" "type_info": "Timestamptz"
},
{
"ordinal": 7,
"name": "last_active_at",
"type_info": "Timestamptz"
},
{
"ordinal": 8,
"name": "last_active_ip: IpAddr",
"type_info": "Inet"
} }
], ],
"parameters": { "parameters": {
@ -51,8 +61,10 @@
false, false,
false, false,
false, false,
true,
true,
true true
] ]
}, },
"hash": "31b7910705963c1a0fa1d55614299aea1a2fa782d40ec53e93c03fe0d73ab0f4" "hash": "31aace373b20b5dbf65fa51d8663da7571d85b6a7d2d544d69e7d04260cdffc9"
} }

View File

@ -1,6 +1,6 @@
{ {
"db_name": "PostgreSQL", "db_name": "PostgreSQL",
"query": "\n SELECT compat_session_id\n , device_id\n , user_id\n , created_at\n , finished_at\n , is_synapse_admin\n FROM compat_sessions\n WHERE user_id = $1\n AND device_id = $2\n ", "query": "\n SELECT compat_session_id\n , device_id\n , user_id\n , created_at\n , finished_at\n , is_synapse_admin\n , last_active_at\n , last_active_ip as \"last_active_ip: IpAddr\"\n FROM compat_sessions\n WHERE user_id = $1\n AND device_id = $2\n ",
"describe": { "describe": {
"columns": [ "columns": [
{ {
@ -32,6 +32,16 @@
"ordinal": 5, "ordinal": 5,
"name": "is_synapse_admin", "name": "is_synapse_admin",
"type_info": "Bool" "type_info": "Bool"
},
{
"ordinal": 6,
"name": "last_active_at",
"type_info": "Timestamptz"
},
{
"ordinal": 7,
"name": "last_active_ip: IpAddr",
"type_info": "Inet"
} }
], ],
"parameters": { "parameters": {
@ -46,8 +56,10 @@
false, false,
false, false,
true, true,
false false,
true,
true
] ]
}, },
"hash": "89e8bb889b8e604d1b4669e904d3233e70b44277e7fe2ce4317c9d821512d86b" "hash": "662ff8972c0cbccb9ba45b1d724c7b6e87656beabe702603cfd4b5a92263b5ab"
} }

View File

@ -58,6 +58,8 @@ struct CompatSessionLookup {
created_at: DateTime<Utc>, created_at: DateTime<Utc>,
finished_at: Option<DateTime<Utc>>, finished_at: Option<DateTime<Utc>>,
is_synapse_admin: bool, is_synapse_admin: bool,
last_active_at: Option<DateTime<Utc>>,
last_active_ip: Option<IpAddr>,
} }
impl TryFrom<CompatSessionLookup> for CompatSession { impl TryFrom<CompatSessionLookup> for CompatSession {
@ -84,6 +86,8 @@ impl TryFrom<CompatSessionLookup> for CompatSession {
device, device,
created_at: value.created_at, created_at: value.created_at,
is_synapse_admin: value.is_synapse_admin, is_synapse_admin: value.is_synapse_admin,
last_active_at: value.last_active_at,
last_active_ip: value.last_active_ip,
}; };
Ok(session) Ok(session)
@ -99,6 +103,8 @@ struct CompatSessionAndSsoLoginLookup {
created_at: DateTime<Utc>, created_at: DateTime<Utc>,
finished_at: Option<DateTime<Utc>>, finished_at: Option<DateTime<Utc>>,
is_synapse_admin: bool, is_synapse_admin: bool,
last_active_at: Option<DateTime<Utc>>,
last_active_ip: Option<IpAddr>,
compat_sso_login_id: Option<Uuid>, compat_sso_login_id: Option<Uuid>,
compat_sso_login_token: Option<String>, compat_sso_login_token: Option<String>,
compat_sso_login_redirect_uri: Option<String>, compat_sso_login_redirect_uri: Option<String>,
@ -131,6 +137,8 @@ impl TryFrom<CompatSessionAndSsoLoginLookup> for (CompatSession, Option<CompatSs
device, device,
created_at: value.created_at, created_at: value.created_at,
is_synapse_admin: value.is_synapse_admin, is_synapse_admin: value.is_synapse_admin,
last_active_at: value.last_active_at,
last_active_ip: value.last_active_ip,
}; };
match ( match (
@ -209,6 +217,8 @@ impl<'c> CompatSessionRepository for PgCompatSessionRepository<'c> {
, created_at , created_at
, finished_at , finished_at
, is_synapse_admin , is_synapse_admin
, last_active_at
, last_active_ip as "last_active_ip: IpAddr"
FROM compat_sessions FROM compat_sessions
WHERE compat_session_id = $1 WHERE compat_session_id = $1
"#, "#,
@ -247,6 +257,8 @@ impl<'c> CompatSessionRepository for PgCompatSessionRepository<'c> {
, created_at , created_at
, finished_at , finished_at
, is_synapse_admin , is_synapse_admin
, last_active_at
, last_active_ip as "last_active_ip: IpAddr"
FROM compat_sessions FROM compat_sessions
WHERE user_id = $1 WHERE user_id = $1
AND device_id = $2 AND device_id = $2
@ -309,6 +321,8 @@ impl<'c> CompatSessionRepository for PgCompatSessionRepository<'c> {
device, device,
created_at, created_at,
is_synapse_admin, is_synapse_admin,
last_active_at: None,
last_active_ip: None,
}) })
} }
@ -390,6 +404,14 @@ impl<'c> CompatSessionRepository for PgCompatSessionRepository<'c> {
Expr::col((CompatSessions::Table, CompatSessions::IsSynapseAdmin)), Expr::col((CompatSessions::Table, CompatSessions::IsSynapseAdmin)),
CompatSessionAndSsoLoginLookupIden::IsSynapseAdmin, CompatSessionAndSsoLoginLookupIden::IsSynapseAdmin,
) )
.expr_as(
Expr::col((CompatSessions::Table, CompatSessions::LastActiveAt)),
CompatSessionAndSsoLoginLookupIden::LastActiveAt,
)
.expr_as(
Expr::col((CompatSessions::Table, CompatSessions::LastActiveIp)),
CompatSessionAndSsoLoginLookupIden::LastActiveIp,
)
.expr_as( .expr_as(
Expr::col((CompatSsoLogins::Table, CompatSsoLogins::CompatSsoLoginId)), Expr::col((CompatSsoLogins::Table, CompatSsoLogins::CompatSsoLoginId)),
CompatSessionAndSsoLoginLookupIden::CompatSsoLoginId, CompatSessionAndSsoLoginLookupIden::CompatSsoLoginId,

View File

@ -22,6 +22,8 @@ pub enum UserSessions {
CreatedAt, CreatedAt,
FinishedAt, FinishedAt,
UserAgent, UserAgent,
LastActiveAt,
LastActiveIp,
} }
#[derive(sea_query::Iden)] #[derive(sea_query::Iden)]
@ -53,6 +55,8 @@ pub enum CompatSessions {
CreatedAt, CreatedAt,
FinishedAt, FinishedAt,
IsSynapseAdmin, IsSynapseAdmin,
LastActiveAt,
LastActiveIp,
} }
#[derive(sea_query::Iden)] #[derive(sea_query::Iden)]
@ -80,6 +84,8 @@ pub enum OAuth2Sessions {
ScopeList, ScopeList,
CreatedAt, CreatedAt,
FinishedAt, FinishedAt,
LastActiveAt,
LastActiveIp,
} }
#[derive(sea_query::Iden)] #[derive(sea_query::Iden)]

View File

@ -59,6 +59,8 @@ struct OAuthSessionLookup {
scope_list: Vec<String>, scope_list: Vec<String>,
created_at: DateTime<Utc>, created_at: DateTime<Utc>,
finished_at: Option<DateTime<Utc>>, finished_at: Option<DateTime<Utc>>,
last_active_at: Option<DateTime<Utc>>,
last_active_ip: Option<IpAddr>,
} }
impl TryFrom<OAuthSessionLookup> for Session { impl TryFrom<OAuthSessionLookup> for Session {
@ -91,6 +93,8 @@ impl TryFrom<OAuthSessionLookup> for Session {
user_id: value.user_id.map(Ulid::from), user_id: value.user_id.map(Ulid::from),
user_session_id: value.user_session_id.map(Ulid::from), user_session_id: value.user_session_id.map(Ulid::from),
scope, scope,
last_active_at: value.last_active_at,
last_active_ip: value.last_active_ip,
}) })
} }
} }
@ -119,6 +123,8 @@ impl<'c> OAuth2SessionRepository for PgOAuth2SessionRepository<'c> {
, scope_list , scope_list
, created_at , created_at
, finished_at , finished_at
, last_active_at
, last_active_ip as "last_active_ip: IpAddr"
FROM oauth2_sessions FROM oauth2_sessions
WHERE oauth2_session_id = $1 WHERE oauth2_session_id = $1
@ -191,6 +197,8 @@ impl<'c> OAuth2SessionRepository for PgOAuth2SessionRepository<'c> {
user_session_id: user_session.map(|s| s.id), user_session_id: user_session.map(|s| s.id),
client_id: client.id, client_id: client.id,
scope, scope,
last_active_at: None,
last_active_ip: None,
}) })
} }
@ -273,6 +281,14 @@ impl<'c> OAuth2SessionRepository for PgOAuth2SessionRepository<'c> {
Expr::col((OAuth2Sessions::Table, OAuth2Sessions::FinishedAt)), Expr::col((OAuth2Sessions::Table, OAuth2Sessions::FinishedAt)),
OAuthSessionLookupIden::FinishedAt, OAuthSessionLookupIden::FinishedAt,
) )
.expr_as(
Expr::col((OAuth2Sessions::Table, OAuth2Sessions::LastActiveAt)),
OAuthSessionLookupIden::LastActiveAt,
)
.expr_as(
Expr::col((OAuth2Sessions::Table, OAuth2Sessions::LastActiveIp)),
OAuthSessionLookupIden::LastActiveIp,
)
.from(OAuth2Sessions::Table) .from(OAuth2Sessions::Table)
.and_where_option(filter.user().map(|user| { .and_where_option(filter.user().map(|user| {
Expr::col((OAuth2Sessions::Table, OAuth2Sessions::UserId)).eq(Uuid::from(user.id)) Expr::col((OAuth2Sessions::Table, OAuth2Sessions::UserId)).eq(Uuid::from(user.id))

View File

@ -56,6 +56,8 @@ struct SessionLookup {
user_session_created_at: DateTime<Utc>, user_session_created_at: DateTime<Utc>,
user_session_finished_at: Option<DateTime<Utc>>, user_session_finished_at: Option<DateTime<Utc>>,
user_session_user_agent: Option<String>, user_session_user_agent: Option<String>,
user_session_last_active_at: Option<DateTime<Utc>>,
user_session_last_active_ip: Option<IpAddr>,
user_id: Uuid, user_id: Uuid,
user_username: String, user_username: String,
user_primary_user_email_id: Option<Uuid>, user_primary_user_email_id: Option<Uuid>,
@ -83,6 +85,8 @@ impl TryFrom<SessionLookup> for BrowserSession {
created_at: value.user_session_created_at, created_at: value.user_session_created_at,
finished_at: value.user_session_finished_at, finished_at: value.user_session_finished_at,
user_agent: value.user_session_user_agent, 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,
}) })
} }
} }
@ -144,6 +148,8 @@ impl<'c> BrowserSessionRepository for PgBrowserSessionRepository<'c> {
, s.created_at AS "user_session_created_at" , s.created_at AS "user_session_created_at"
, s.finished_at AS "user_session_finished_at" , s.finished_at AS "user_session_finished_at"
, s.user_agent AS "user_session_user_agent" , s.user_agent AS "user_session_user_agent"
, s.last_active_at AS "user_session_last_active_at"
, s.last_active_ip AS "user_session_last_active_ip: IpAddr"
, u.user_id , u.user_id
, u.username AS "user_username" , u.username AS "user_username"
, u.primary_user_email_id AS "user_primary_user_email_id" , u.primary_user_email_id AS "user_primary_user_email_id"
@ -207,6 +213,8 @@ impl<'c> BrowserSessionRepository for PgBrowserSessionRepository<'c> {
created_at, created_at,
finished_at: None, finished_at: None,
user_agent, user_agent,
last_active_at: None,
last_active_ip: None,
}; };
Ok(session) Ok(session)
@ -277,6 +285,14 @@ impl<'c> BrowserSessionRepository for PgBrowserSessionRepository<'c> {
Expr::col((UserSessions::Table, UserSessions::UserAgent)), Expr::col((UserSessions::Table, UserSessions::UserAgent)),
SessionLookupIden::UserSessionUserAgent, SessionLookupIden::UserSessionUserAgent,
) )
.expr_as(
Expr::col((UserSessions::Table, UserSessions::LastActiveAt)),
SessionLookupIden::UserSessionLastActiveAt,
)
.expr_as(
Expr::col((UserSessions::Table, UserSessions::LastActiveIp)),
SessionLookupIden::UserSessionLastActiveIp,
)
.expr_as( .expr_as(
Expr::col((Users::Table, Users::UserId)), Expr::col((Users::Table, Users::UserId)),
SessionLookupIden::UserId, SessionLookupIden::UserId,

View File

@ -157,6 +157,14 @@ type BrowserSession implements Node & CreationEvent {
The user-agent string with which the session was created. The user-agent string with which the session was created.
""" """
userAgent: String userAgent: String
"""
The last IP address used by the session.
"""
lastActiveIp: String
"""
The last time the session was active.
"""
lastActiveAt: DateTime
} }
type BrowserSessionConnection { type BrowserSessionConnection {
@ -239,6 +247,14 @@ type CompatSession implements Node & CreationEvent {
The state of the session. The state of the session.
""" """
state: CompatSessionState! state: CompatSessionState!
"""
The last IP address used by the session.
"""
lastActiveIp: String
"""
The last time the session was active.
"""
lastActiveAt: DateTime
} }
type CompatSessionConnection { type CompatSessionConnection {
@ -740,6 +756,14 @@ type Oauth2Session implements Node & CreationEvent {
User authorized for this session. User authorized for this session.
""" """
user: User user: User
"""
The last IP address used by the session.
"""
lastActiveIp: String
"""
The last time the session was active.
"""
lastActiveAt: DateTime
} }
type Oauth2SessionConnection { type Oauth2SessionConnection {

View File

@ -127,6 +127,10 @@ export type BrowserSession = CreationEvent &
finishedAt?: Maybe<Scalars["DateTime"]["output"]>; finishedAt?: Maybe<Scalars["DateTime"]["output"]>;
/** ID of the object. */ /** ID of the object. */
id: Scalars["ID"]["output"]; id: Scalars["ID"]["output"];
/** The last time the session was active. */
lastActiveAt?: Maybe<Scalars["DateTime"]["output"]>;
/** The last IP address used by the session. */
lastActiveIp?: Maybe<Scalars["String"]["output"]>;
/** The most recent authentication of this session. */ /** The most recent authentication of this session. */
lastAuthentication?: Maybe<Authentication>; lastAuthentication?: Maybe<Authentication>;
/** The state of the session. */ /** The state of the session. */
@ -181,6 +185,10 @@ export type CompatSession = CreationEvent &
finishedAt?: Maybe<Scalars["DateTime"]["output"]>; finishedAt?: Maybe<Scalars["DateTime"]["output"]>;
/** ID of the object. */ /** ID of the object. */
id: Scalars["ID"]["output"]; id: Scalars["ID"]["output"];
/** The last time the session was active. */
lastActiveAt?: Maybe<Scalars["DateTime"]["output"]>;
/** The last IP address used by the session. */
lastActiveIp?: Maybe<Scalars["String"]["output"]>;
/** The associated SSO login, if any. */ /** The associated SSO login, if any. */
ssoLogin?: Maybe<CompatSsoLogin>; ssoLogin?: Maybe<CompatSsoLogin>;
/** The state of the session. */ /** The state of the session. */
@ -544,6 +552,10 @@ export type Oauth2Session = CreationEvent &
finishedAt?: Maybe<Scalars["DateTime"]["output"]>; finishedAt?: Maybe<Scalars["DateTime"]["output"]>;
/** ID of the object. */ /** ID of the object. */
id: Scalars["ID"]["output"]; id: Scalars["ID"]["output"];
/** The last time the session was active. */
lastActiveAt?: Maybe<Scalars["DateTime"]["output"]>;
/** The last IP address used by the session. */
lastActiveIp?: Maybe<Scalars["String"]["output"]>;
/** Scope granted for this session. */ /** Scope granted for this session. */
scope: Scalars["String"]["output"]; scope: Scalars["String"]["output"];
/** The state of the session. */ /** The state of the session. */

File diff suppressed because it is too large Load Diff