graphql: allow filtering of sessions by last activity
This commit is contained in:
@@ -19,7 +19,7 @@ use std::sync::Arc;
|
||||
use async_graphql::{
|
||||
extensions::Tracing,
|
||||
http::{playground_source, GraphQLPlaygroundConfig, MultipartOptions},
|
||||
EmptySubscription,
|
||||
EmptySubscription, InputObject,
|
||||
};
|
||||
use axum::{
|
||||
async_trait,
|
||||
@@ -30,6 +30,7 @@ use axum::{
|
||||
Json,
|
||||
};
|
||||
use axum_extra::typed_header::TypedHeader;
|
||||
use chrono::{DateTime, Utc};
|
||||
use futures_util::TryStreamExt;
|
||||
use headers::{authorization::Bearer, Authorization, ContentType, HeaderValue};
|
||||
use hyper::header::CACHE_CONTROL;
|
||||
@@ -501,3 +502,13 @@ where
|
||||
session.map(Into::into).unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
/// A filter for dates, with a lower bound and an upper bound
|
||||
#[derive(InputObject, Default, Clone, Copy)]
|
||||
pub struct DateFilter {
|
||||
/// The lower bound of the date range
|
||||
after: Option<DateTime<Utc>>,
|
||||
|
||||
/// The upper bound of the date range
|
||||
before: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
// Copyright 2022-2024 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -34,7 +34,7 @@ use super::{
|
||||
BrowserSession, CompatSession, Cursor, NodeCursor, NodeType, OAuth2Session,
|
||||
PreloadedTotalCount, SessionState, UpstreamOAuth2Link,
|
||||
};
|
||||
use crate::graphql::state::ContextExt;
|
||||
use crate::graphql::{state::ContextExt, DateFilter};
|
||||
|
||||
#[derive(Description)]
|
||||
/// A user is an individual's account.
|
||||
@@ -171,6 +171,12 @@ impl User {
|
||||
#[graphql(name = "type", desc = "List only sessions with the given type.")]
|
||||
type_param: Option<CompatSessionType>,
|
||||
|
||||
#[graphql(
|
||||
name = "lastActive",
|
||||
desc = "List only sessions with a last active time is between the given bounds."
|
||||
)]
|
||||
last_active: Option<DateFilter>,
|
||||
|
||||
#[graphql(desc = "Returns the elements in the list that come after the cursor.")]
|
||||
after: Option<String>,
|
||||
#[graphql(desc = "Returns the elements in the list that come before the cursor.")]
|
||||
@@ -180,6 +186,7 @@ impl User {
|
||||
) -> Result<Connection<Cursor, CompatSession, PreloadedTotalCount>, async_graphql::Error> {
|
||||
let state = ctx.state();
|
||||
let mut repo = state.repository().await?;
|
||||
let last_active = last_active.unwrap_or_default();
|
||||
|
||||
query(
|
||||
after,
|
||||
@@ -208,6 +215,15 @@ impl User {
|
||||
None => filter,
|
||||
};
|
||||
|
||||
let filter = match last_active.after {
|
||||
Some(after) => filter.with_last_active_after(after),
|
||||
None => filter,
|
||||
};
|
||||
let filter = match last_active.before {
|
||||
Some(before) => filter.with_last_active_before(before),
|
||||
None => filter,
|
||||
};
|
||||
|
||||
let page = repo.compat_session().list(filter, pagination).await?;
|
||||
|
||||
// Preload the total count if requested
|
||||
@@ -247,6 +263,12 @@ impl User {
|
||||
#[graphql(name = "state", desc = "List only sessions in the given state.")]
|
||||
state_param: Option<SessionState>,
|
||||
|
||||
#[graphql(
|
||||
name = "lastActive",
|
||||
desc = "List only sessions with a last active time is between the given bounds."
|
||||
)]
|
||||
last_active: Option<DateFilter>,
|
||||
|
||||
#[graphql(desc = "Returns the elements in the list that come after the cursor.")]
|
||||
after: Option<String>,
|
||||
#[graphql(desc = "Returns the elements in the list that come before the cursor.")]
|
||||
@@ -256,6 +278,7 @@ impl User {
|
||||
) -> Result<Connection<Cursor, BrowserSession, PreloadedTotalCount>, async_graphql::Error> {
|
||||
let state = ctx.state();
|
||||
let mut repo = state.repository().await?;
|
||||
let last_active = last_active.unwrap_or_default();
|
||||
|
||||
query(
|
||||
after,
|
||||
@@ -278,6 +301,15 @@ impl User {
|
||||
None => filter,
|
||||
};
|
||||
|
||||
let filter = match last_active.after {
|
||||
Some(after) => filter.with_last_active_after(after),
|
||||
None => filter,
|
||||
};
|
||||
let filter = match last_active.before {
|
||||
Some(before) => filter.with_last_active_before(before),
|
||||
None => filter,
|
||||
};
|
||||
|
||||
let page = repo.browser_session().list(filter, pagination).await?;
|
||||
|
||||
// Preload the total count if requested
|
||||
@@ -387,6 +419,12 @@ impl User {
|
||||
|
||||
#[graphql(desc = "List only sessions for the given client.")] client: Option<ID>,
|
||||
|
||||
#[graphql(
|
||||
name = "lastActive",
|
||||
desc = "List only sessions with a last active time is between the given bounds."
|
||||
)]
|
||||
last_active: Option<DateFilter>,
|
||||
|
||||
#[graphql(desc = "Returns the elements in the list that come after the cursor.")]
|
||||
after: Option<String>,
|
||||
#[graphql(desc = "Returns the elements in the list that come before the cursor.")]
|
||||
@@ -396,6 +434,7 @@ impl User {
|
||||
) -> Result<Connection<Cursor, OAuth2Session, PreloadedTotalCount>, async_graphql::Error> {
|
||||
let state = ctx.state();
|
||||
let mut repo = state.repository().await?;
|
||||
let last_active = last_active.unwrap_or_default();
|
||||
|
||||
query(
|
||||
after,
|
||||
@@ -438,6 +477,15 @@ impl User {
|
||||
None => filter,
|
||||
};
|
||||
|
||||
let filter = match last_active.after {
|
||||
Some(after) => filter.with_last_active_after(after),
|
||||
None => filter,
|
||||
};
|
||||
let filter = match last_active.before {
|
||||
Some(before) => filter.with_last_active_before(before),
|
||||
None => filter,
|
||||
};
|
||||
|
||||
let page = repo.oauth2_session().list(filter, pagination).await?;
|
||||
|
||||
let count = if ctx.look_ahead().field("totalCount").exists() {
|
||||
@@ -547,6 +595,12 @@ impl User {
|
||||
#[graphql(name = "device", desc = "List only sessions for the given device.")]
|
||||
device_param: Option<String>,
|
||||
|
||||
#[graphql(
|
||||
name = "lastActive",
|
||||
desc = "List only sessions with a last active time is between the given bounds."
|
||||
)]
|
||||
last_active: Option<DateFilter>,
|
||||
|
||||
#[graphql(
|
||||
name = "browserSession",
|
||||
desc = "List only sessions for the given session."
|
||||
@@ -563,6 +617,7 @@ impl User {
|
||||
let state = ctx.state();
|
||||
let requester = ctx.requester();
|
||||
let mut repo = state.repository().await?;
|
||||
let last_active = last_active.unwrap_or_default();
|
||||
|
||||
query(
|
||||
after,
|
||||
@@ -629,6 +684,15 @@ impl User {
|
||||
None => filter,
|
||||
};
|
||||
|
||||
let filter = match last_active.after {
|
||||
Some(after) => filter.with_last_active_after(after),
|
||||
None => filter,
|
||||
};
|
||||
let filter = match last_active.before {
|
||||
Some(before) => filter.with_last_active_before(before),
|
||||
None => filter,
|
||||
};
|
||||
|
||||
let page = repo.app_session().list(filter, pagination).await?;
|
||||
|
||||
let count = if ctx.look_ahead().field("totalCount").exists() {
|
||||
|
||||
@@ -509,6 +509,20 @@ interface CreationEvent {
|
||||
createdAt: DateTime!
|
||||
}
|
||||
|
||||
"""
|
||||
A filter for dates, with a lower bound and an upper bound
|
||||
"""
|
||||
input DateFilter {
|
||||
"""
|
||||
The lower bound of the date range
|
||||
"""
|
||||
after: DateTime
|
||||
"""
|
||||
The upper bound of the date range
|
||||
"""
|
||||
before: DateTime
|
||||
}
|
||||
|
||||
"""
|
||||
Implement the DateTime<Utc> scalar
|
||||
|
||||
@@ -1624,6 +1638,10 @@ type User implements Node {
|
||||
"""
|
||||
type: CompatSessionType
|
||||
"""
|
||||
List only sessions with a last active time is between the given bounds.
|
||||
"""
|
||||
lastActive: DateFilter
|
||||
"""
|
||||
Returns the elements in the list that come after the cursor.
|
||||
"""
|
||||
after: String
|
||||
@@ -1649,6 +1667,10 @@ type User implements Node {
|
||||
"""
|
||||
state: SessionState
|
||||
"""
|
||||
List only sessions with a last active time is between the given bounds.
|
||||
"""
|
||||
lastActive: DateFilter
|
||||
"""
|
||||
Returns the elements in the list that come after the cursor.
|
||||
"""
|
||||
after: String
|
||||
@@ -1703,6 +1725,10 @@ type User implements Node {
|
||||
"""
|
||||
client: ID
|
||||
"""
|
||||
List only sessions with a last active time is between the given bounds.
|
||||
"""
|
||||
lastActive: DateFilter
|
||||
"""
|
||||
Returns the elements in the list that come after the cursor.
|
||||
"""
|
||||
after: String
|
||||
@@ -1754,6 +1780,10 @@ type User implements Node {
|
||||
"""
|
||||
device: String
|
||||
"""
|
||||
List only sessions with a last active time is between the given bounds.
|
||||
"""
|
||||
lastActive: DateFilter
|
||||
"""
|
||||
List only sessions for the given session.
|
||||
"""
|
||||
browserSession: ID
|
||||
|
||||
@@ -342,6 +342,14 @@ export type CreationEvent = {
|
||||
createdAt: Scalars['DateTime']['output'];
|
||||
};
|
||||
|
||||
/** A filter for dates, with a lower bound and an upper bound */
|
||||
export type DateFilter = {
|
||||
/** The lower bound of the date range */
|
||||
after?: InputMaybe<Scalars['DateTime']['input']>;
|
||||
/** The upper bound of the date range */
|
||||
before?: InputMaybe<Scalars['DateTime']['input']>;
|
||||
};
|
||||
|
||||
/** The type of a user agent */
|
||||
export enum DeviceType {
|
||||
/** A mobile phone. Can also sometimes be a tablet. */
|
||||
@@ -1186,6 +1194,7 @@ export type UserAppSessionsArgs = {
|
||||
device?: InputMaybe<Scalars['String']['input']>;
|
||||
first?: InputMaybe<Scalars['Int']['input']>;
|
||||
last?: InputMaybe<Scalars['Int']['input']>;
|
||||
lastActive?: InputMaybe<DateFilter>;
|
||||
state?: InputMaybe<SessionState>;
|
||||
};
|
||||
|
||||
@@ -1196,6 +1205,7 @@ export type UserBrowserSessionsArgs = {
|
||||
before?: InputMaybe<Scalars['String']['input']>;
|
||||
first?: InputMaybe<Scalars['Int']['input']>;
|
||||
last?: InputMaybe<Scalars['Int']['input']>;
|
||||
lastActive?: InputMaybe<DateFilter>;
|
||||
state?: InputMaybe<SessionState>;
|
||||
};
|
||||
|
||||
@@ -1206,6 +1216,7 @@ export type UserCompatSessionsArgs = {
|
||||
before?: InputMaybe<Scalars['String']['input']>;
|
||||
first?: InputMaybe<Scalars['Int']['input']>;
|
||||
last?: InputMaybe<Scalars['Int']['input']>;
|
||||
lastActive?: InputMaybe<DateFilter>;
|
||||
state?: InputMaybe<SessionState>;
|
||||
type?: InputMaybe<CompatSessionType>;
|
||||
};
|
||||
@@ -1237,6 +1248,7 @@ export type UserOauth2SessionsArgs = {
|
||||
client?: InputMaybe<Scalars['ID']['input']>;
|
||||
first?: InputMaybe<Scalars['Int']['input']>;
|
||||
last?: InputMaybe<Scalars['Int']['input']>;
|
||||
lastActive?: InputMaybe<DateFilter>;
|
||||
state?: InputMaybe<SessionState>;
|
||||
};
|
||||
|
||||
|
||||
@@ -3062,6 +3062,13 @@ export default {
|
||||
"name": "Any"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lastActive",
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Any"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "state",
|
||||
"type": {
|
||||
@@ -3110,6 +3117,13 @@ export default {
|
||||
"name": "Any"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lastActive",
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Any"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "state",
|
||||
"type": {
|
||||
@@ -3169,6 +3183,13 @@ export default {
|
||||
"name": "Any"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lastActive",
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Any"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "state",
|
||||
"type": {
|
||||
@@ -3362,6 +3383,13 @@ export default {
|
||||
"name": "Any"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "lastActive",
|
||||
"type": {
|
||||
"kind": "SCALAR",
|
||||
"name": "Any"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "state",
|
||||
"type": {
|
||||
|
||||
Reference in New Issue
Block a user