You've already forked authentication-service
mirror of
https://github.com/matrix-org/matrix-authentication-service.git
synced 2025-08-07 17:03:01 +03:00
Simple list of compat sessions
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -2605,7 +2605,9 @@ dependencies = [
|
||||
"oauth2-types",
|
||||
"serde",
|
||||
"sqlx",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"ulid",
|
||||
"url",
|
||||
]
|
||||
|
@@ -10,7 +10,9 @@ async-graphql = { version = "4.0.16", features = ["chrono", "url"] }
|
||||
chrono = "0.4.23"
|
||||
serde = { version = "1.0.147", features = ["derive"] }
|
||||
sqlx = { version = "0.6.2", features = ["runtime-tokio-rustls", "postgres"] }
|
||||
thiserror = "1.0.37"
|
||||
tokio = { version = "1.21.2", features = ["time"] }
|
||||
tracing = "0.1.37"
|
||||
ulid = "1.0.0"
|
||||
url = "2.3.1"
|
||||
|
||||
|
@@ -22,8 +22,9 @@
|
||||
#![warn(clippy::pedantic)]
|
||||
#![allow(clippy::module_name_repetitions, clippy::missing_errors_doc)]
|
||||
|
||||
use async_graphql::{Context, Description, EmptyMutation, EmptySubscription};
|
||||
use async_graphql::{Context, Description, EmptyMutation, EmptySubscription, ID};
|
||||
use mas_axum_utils::SessionInfo;
|
||||
use model::NodeType;
|
||||
use sqlx::PgPool;
|
||||
|
||||
use self::model::{BrowserSession, Node, User};
|
||||
@@ -78,4 +79,34 @@ impl RootQuery {
|
||||
|
||||
Ok(session.map(User::from))
|
||||
}
|
||||
|
||||
/// Fetches an object given its ID.
|
||||
async fn node(&self, ctx: &Context<'_>, id: ID) -> Result<Option<Node>, async_graphql::Error> {
|
||||
let (node_type, id) = NodeType::from_id(&id)?;
|
||||
let database = ctx.data::<PgPool>()?;
|
||||
let session_info = ctx.data::<SessionInfo>()?;
|
||||
let mut conn = database.acquire().await?;
|
||||
let session = session_info.load_session(&mut conn).await?;
|
||||
|
||||
let Some(session) = session else { return Ok(None) };
|
||||
|
||||
match node_type {
|
||||
// TODO
|
||||
NodeType::Authentication
|
||||
| NodeType::BrowserSession
|
||||
| NodeType::CompatSession
|
||||
| NodeType::CompatSsoLogin
|
||||
| NodeType::OAuth2Client
|
||||
| NodeType::UserEmail
|
||||
| NodeType::OAuth2Session => Ok(None),
|
||||
|
||||
NodeType::User => {
|
||||
if session.user.data == id {
|
||||
Ok(Some(Box::new(User(session.user)).into()))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -16,7 +16,7 @@ use async_graphql::{Description, Object, ID};
|
||||
use chrono::{DateTime, Utc};
|
||||
use mas_storage::PostgresqlBackend;
|
||||
|
||||
use super::User;
|
||||
use super::{NodeType, User};
|
||||
|
||||
/// A browser session represents a logged in user in a browser.
|
||||
#[derive(Description)]
|
||||
@@ -32,7 +32,7 @@ impl From<mas_data_model::BrowserSession<PostgresqlBackend>> for BrowserSession
|
||||
impl BrowserSession {
|
||||
/// ID of the object.
|
||||
pub async fn id(&self) -> ID {
|
||||
ID(self.0.data.to_string())
|
||||
NodeType::BrowserSession.id(self.0.data)
|
||||
}
|
||||
|
||||
/// The user logged in this session.
|
||||
@@ -60,7 +60,7 @@ pub struct Authentication(pub mas_data_model::Authentication<PostgresqlBackend>)
|
||||
impl Authentication {
|
||||
/// ID of the object.
|
||||
pub async fn id(&self) -> ID {
|
||||
ID(self.0.data.to_string())
|
||||
NodeType::Authentication.id(self.0.data)
|
||||
}
|
||||
|
||||
/// When the object was created.
|
||||
|
@@ -18,7 +18,7 @@ use mas_data_model::CompatSsoLoginState;
|
||||
use mas_storage::PostgresqlBackend;
|
||||
use url::Url;
|
||||
|
||||
use super::User;
|
||||
use super::{NodeType, User};
|
||||
|
||||
/// A compat session represents a client session which used the legacy Matrix
|
||||
/// login API.
|
||||
@@ -29,7 +29,7 @@ pub struct CompatSession(pub mas_data_model::CompatSession<PostgresqlBackend>);
|
||||
impl CompatSession {
|
||||
/// ID of the object.
|
||||
pub async fn id(&self) -> ID {
|
||||
ID(self.0.data.to_string())
|
||||
NodeType::CompatSession.id(self.0.data)
|
||||
}
|
||||
|
||||
/// The user authorized for this session.
|
||||
@@ -62,7 +62,7 @@ pub struct CompatSsoLogin(pub mas_data_model::CompatSsoLogin<PostgresqlBackend>)
|
||||
impl CompatSsoLogin {
|
||||
/// ID of the object.
|
||||
pub async fn id(&self) -> ID {
|
||||
ID(self.0.data.to_string())
|
||||
NodeType::CompatSsoLogin.id(self.0.data)
|
||||
}
|
||||
|
||||
/// When the object was created.
|
||||
|
@@ -16,14 +16,7 @@ use async_graphql::connection::OpaqueCursor;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ulid::Ulid;
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone, Copy)]
|
||||
#[serde(rename = "snake_case")]
|
||||
pub enum NodeType {
|
||||
UserEmail,
|
||||
BrowserSession,
|
||||
CompatSsoLogin,
|
||||
OAuth2Session,
|
||||
}
|
||||
pub use super::NodeType;
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct NodeCursor(pub NodeType, pub Ulid);
|
||||
|
@@ -12,37 +12,25 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use async_graphql::{Interface, ID};
|
||||
use async_graphql::Interface;
|
||||
use chrono::{DateTime, Utc};
|
||||
|
||||
mod browser_sessions;
|
||||
mod compat_sessions;
|
||||
mod cursor;
|
||||
mod node;
|
||||
mod oauth;
|
||||
mod users;
|
||||
|
||||
pub use self::{
|
||||
browser_sessions::{Authentication, BrowserSession},
|
||||
compat_sessions::{CompatSession, CompatSsoLogin},
|
||||
cursor::{Cursor, NodeCursor, NodeType},
|
||||
cursor::{Cursor, NodeCursor},
|
||||
node::{Node, NodeType},
|
||||
oauth::{OAuth2Client, OAuth2Consent, OAuth2Session},
|
||||
users::{User, UserEmail},
|
||||
};
|
||||
|
||||
/// An object with an ID.
|
||||
#[derive(Interface)]
|
||||
#[graphql(field(name = "id", desc = "ID of the object.", type = "ID"))]
|
||||
pub enum Node {
|
||||
Authentication(Box<Authentication>),
|
||||
BrowserSession(Box<BrowserSession>),
|
||||
CompatSession(Box<CompatSession>),
|
||||
CompatSsoLogin(Box<CompatSsoLogin>),
|
||||
OAuth2Client(Box<OAuth2Client>),
|
||||
OAuth2Session(Box<OAuth2Session>),
|
||||
User(Box<User>),
|
||||
UserEmail(Box<UserEmail>),
|
||||
}
|
||||
|
||||
#[derive(Interface)]
|
||||
#[graphql(field(
|
||||
name = "created_at",
|
||||
|
107
crates/graphql/src/model/node.rs
Normal file
107
crates/graphql/src/model/node.rs
Normal file
@@ -0,0 +1,107 @@
|
||||
// Copyright 2022 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.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use async_graphql::{Interface, ID};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
use ulid::Ulid;
|
||||
|
||||
use super::{
|
||||
Authentication, BrowserSession, CompatSession, CompatSsoLogin, OAuth2Client, OAuth2Session,
|
||||
User, UserEmail,
|
||||
};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum NodeType {
|
||||
Authentication,
|
||||
BrowserSession,
|
||||
CompatSession,
|
||||
CompatSsoLogin,
|
||||
OAuth2Client,
|
||||
OAuth2Session,
|
||||
User,
|
||||
UserEmail,
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error("invalid id")]
|
||||
pub enum InvalidID {
|
||||
InvalidFormat,
|
||||
InvalidUlid(#[from] ulid::DecodeError),
|
||||
UnknownPrefix,
|
||||
}
|
||||
|
||||
impl NodeType {
|
||||
fn to_prefix(self) -> &'static str {
|
||||
match self {
|
||||
NodeType::Authentication => "authentication",
|
||||
NodeType::BrowserSession => "browser_session",
|
||||
NodeType::CompatSession => "compat_session",
|
||||
NodeType::CompatSsoLogin => "compat_sso_login",
|
||||
NodeType::OAuth2Client => "oauth2_client",
|
||||
NodeType::OAuth2Session => "oauth2_session",
|
||||
NodeType::User => "user",
|
||||
NodeType::UserEmail => "user_email",
|
||||
}
|
||||
}
|
||||
|
||||
fn from_prefix(prefix: &str) -> Option<Self> {
|
||||
match prefix {
|
||||
"authentication" => Some(NodeType::Authentication),
|
||||
"browser_session" => Some(NodeType::BrowserSession),
|
||||
"compat_session" => Some(NodeType::CompatSession),
|
||||
"compat_sso_login" => Some(NodeType::CompatSsoLogin),
|
||||
"oauth2_client" => Some(NodeType::OAuth2Client),
|
||||
"oauth2_session" => Some(NodeType::OAuth2Session),
|
||||
"user" => Some(NodeType::User),
|
||||
"user_email" => Some(NodeType::UserEmail),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn serialize(self, id: impl Into<Ulid>) -> String {
|
||||
let prefix = self.to_prefix();
|
||||
let id = id.into();
|
||||
format!("{prefix}:{id}")
|
||||
}
|
||||
|
||||
pub fn id(self, id: impl Into<Ulid>) -> ID {
|
||||
ID(self.serialize(id))
|
||||
}
|
||||
|
||||
pub fn deserialize(serialized: &str) -> Result<(Self, Ulid), InvalidID> {
|
||||
let (prefix, id) = serialized.split_once(':').ok_or(InvalidID::InvalidFormat)?;
|
||||
let prefix = NodeType::from_prefix(prefix).ok_or(InvalidID::UnknownPrefix)?;
|
||||
let id = id.parse()?;
|
||||
Ok((prefix, id))
|
||||
}
|
||||
|
||||
pub fn from_id(id: &ID) -> Result<(Self, Ulid), InvalidID> {
|
||||
Self::deserialize(&id.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// An object with an ID.
|
||||
#[derive(Interface)]
|
||||
#[graphql(field(name = "id", desc = "ID of the object.", type = "ID"))]
|
||||
pub enum Node {
|
||||
Authentication(Box<Authentication>),
|
||||
BrowserSession(Box<BrowserSession>),
|
||||
CompatSession(Box<CompatSession>),
|
||||
CompatSsoLogin(Box<CompatSsoLogin>),
|
||||
OAuth2Client(Box<OAuth2Client>),
|
||||
OAuth2Session(Box<OAuth2Session>),
|
||||
User(Box<User>),
|
||||
UserEmail(Box<UserEmail>),
|
||||
}
|
@@ -19,7 +19,7 @@ use sqlx::PgPool;
|
||||
use ulid::Ulid;
|
||||
use url::Url;
|
||||
|
||||
use super::{BrowserSession, User};
|
||||
use super::{BrowserSession, NodeType, User};
|
||||
|
||||
/// An OAuth 2.0 session represents a client session which used the OAuth APIs
|
||||
/// to login.
|
||||
@@ -30,7 +30,7 @@ pub struct OAuth2Session(pub mas_data_model::Session<PostgresqlBackend>);
|
||||
impl OAuth2Session {
|
||||
/// ID of the object.
|
||||
pub async fn id(&self) -> ID {
|
||||
ID(self.0.data.to_string())
|
||||
NodeType::OAuth2Session.id(self.0.data)
|
||||
}
|
||||
|
||||
/// OAuth 2.0 client used by this session.
|
||||
@@ -62,7 +62,7 @@ pub struct OAuth2Client(pub mas_data_model::Client<PostgresqlBackend>);
|
||||
impl OAuth2Client {
|
||||
/// ID of the object.
|
||||
pub async fn id(&self) -> ID {
|
||||
ID(self.0.data.to_string())
|
||||
NodeType::OAuth2Client.id(self.0.data)
|
||||
}
|
||||
|
||||
/// OAuth 2.0 client ID
|
||||
|
@@ -44,7 +44,7 @@ impl From<mas_data_model::BrowserSession<PostgresqlBackend>> for User {
|
||||
impl User {
|
||||
/// ID of the object.
|
||||
pub async fn id(&self) -> ID {
|
||||
ID(self.0.data.to_string())
|
||||
NodeType::User.id(self.0.data)
|
||||
}
|
||||
|
||||
/// Username chosen by the user.
|
||||
@@ -79,10 +79,10 @@ impl User {
|
||||
|after, before, first, last| async move {
|
||||
let mut conn = database.acquire().await?;
|
||||
let after_id = after
|
||||
.map(|x: OpaqueCursor<NodeCursor>| x.extract_for_type(NodeType::UserEmail))
|
||||
.map(|x: OpaqueCursor<NodeCursor>| x.extract_for_type(NodeType::CompatSsoLogin))
|
||||
.transpose()?;
|
||||
let before_id = before
|
||||
.map(|x: OpaqueCursor<NodeCursor>| x.extract_for_type(NodeType::UserEmail))
|
||||
.map(|x: OpaqueCursor<NodeCursor>| x.extract_for_type(NodeType::CompatSsoLogin))
|
||||
.transpose()?;
|
||||
|
||||
let (has_previous_page, has_next_page, edges) =
|
||||
@@ -262,7 +262,7 @@ pub struct UserEmail(mas_data_model::UserEmail<PostgresqlBackend>);
|
||||
impl UserEmail {
|
||||
/// ID of the object.
|
||||
pub async fn id(&self) -> ID {
|
||||
ID(self.0.data.to_string())
|
||||
NodeType::UserEmail.id(self.0.data)
|
||||
}
|
||||
|
||||
/// Email address
|
||||
|
@@ -88,10 +88,8 @@ module.exports = {
|
||||
rules: {
|
||||
"@graphql-eslint/known-fragment-names": "off",
|
||||
"@graphql-eslint/no-unused-fragments": "off",
|
||||
"@graphql-eslint/known-directives": [
|
||||
"error",
|
||||
{ ignoreClientDirectives: ["connection", "refetchable"] },
|
||||
],
|
||||
"@graphql-eslint/unused-arguments": "off",
|
||||
"@graphql-eslint/known-directives": "off",
|
||||
// This rule is copied from the 'operations-recommended' config,
|
||||
// but without the 'Query' forbidden suffix on operations,
|
||||
// since it directly clashes with the relay operation naming convention
|
||||
|
@@ -293,6 +293,10 @@ type RootQuery {
|
||||
Get the current logged in user
|
||||
"""
|
||||
currentUser: User
|
||||
"""
|
||||
Fetches an object given its ID.
|
||||
"""
|
||||
node(id: ID!): Node
|
||||
}
|
||||
|
||||
"""
|
||||
|
@@ -25,12 +25,53 @@ const CompatSsoLogin: React.FC<Props> = ({ login }) => {
|
||||
fragment CompatSsoLogin_login on CompatSsoLogin {
|
||||
id
|
||||
redirectUri
|
||||
createdAt
|
||||
session {
|
||||
id
|
||||
createdAt
|
||||
deviceId
|
||||
finishedAt
|
||||
}
|
||||
}
|
||||
`,
|
||||
login
|
||||
);
|
||||
|
||||
return <>{data.redirectUri}</>;
|
||||
let info = null;
|
||||
if (data.session) {
|
||||
info = (
|
||||
<>
|
||||
<div>
|
||||
Started:{" "}
|
||||
<span className="font-mono text-sm">{data.session.createdAt}</span>
|
||||
</div>
|
||||
{data.session.finishedAt ? (
|
||||
<div className="text-alert">
|
||||
Finished:{" "}
|
||||
<span className="font-mono text-sm">{data.session.createdAt}</span>
|
||||
</div>
|
||||
) : null}
|
||||
<div>
|
||||
Device ID:{" "}
|
||||
<span className="font-mono text-sm font-semibold">
|
||||
{data.session.deviceId}
|
||||
</span>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="p-2 my-1 bg-grey-50 dark:bg-grey-450 rounded">
|
||||
<div>
|
||||
Requested: <span className="font-mono text-sm">{data.createdAt}</span>
|
||||
</div>
|
||||
{info}
|
||||
<div>
|
||||
Redirect URI: <span className="font-semibold">{data.redirectUri}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CompatSsoLogin;
|
||||
|
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { graphql, useFragment } from "react-relay";
|
||||
import { graphql, usePaginationFragment } from "react-relay";
|
||||
import CompatSsoLogin from "./CompatSsoLogin";
|
||||
import { CompatSsoLoginList_user$key } from "./__generated__/CompatSsoLoginList_user.graphql";
|
||||
|
||||
@@ -21,12 +21,15 @@ type Props = {
|
||||
};
|
||||
|
||||
const CompatSsoLoginList: React.FC<Props> = ({ user }) => {
|
||||
const data = useFragment(
|
||||
const { data, loadNext, hasNext } = usePaginationFragment(
|
||||
graphql`
|
||||
fragment CompatSsoLoginList_user on User {
|
||||
compatSsoLogins(first: 10) {
|
||||
fragment CompatSsoLoginList_user on User
|
||||
@refetchable(queryName: "CompatSsoLoginListQuery") {
|
||||
compatSsoLogins(first: $count, after: $cursor)
|
||||
@connection(key: "CompatSsoLoginList_user_compatSsoLogins") {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
...CompatSsoLogin_login
|
||||
}
|
||||
}
|
||||
@@ -37,10 +40,16 @@ const CompatSsoLoginList: React.FC<Props> = ({ user }) => {
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="w-96">
|
||||
<h2 className="text-lg">List of compatibility sessions:</h2>
|
||||
{data.compatSsoLogins.edges.map((n) => (
|
||||
<CompatSsoLogin login={n.node} />
|
||||
<CompatSsoLogin login={n.node} key={n.node.id} />
|
||||
))}
|
||||
{hasNext ? (
|
||||
<button className="bg-accent p-2 rounded" onClick={() => loadNext(2)}>
|
||||
Load more
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
265
frontend/src/components/__generated__/CompatSsoLoginListQuery.graphql.ts
generated
Normal file
265
frontend/src/components/__generated__/CompatSsoLoginListQuery.graphql.ts
generated
Normal file
@@ -0,0 +1,265 @@
|
||||
/**
|
||||
* @generated SignedSource<<3e111db0c30af3251a88326deea5562c>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest, Query } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type CompatSsoLoginListQuery$variables = {
|
||||
count?: number | null;
|
||||
cursor?: string | null;
|
||||
id: string;
|
||||
};
|
||||
export type CompatSsoLoginListQuery$data = {
|
||||
readonly node: {
|
||||
readonly " $fragmentSpreads": FragmentRefs<"CompatSsoLoginList_user">;
|
||||
} | null;
|
||||
};
|
||||
export type CompatSsoLoginListQuery = {
|
||||
response: CompatSsoLoginListQuery$data;
|
||||
variables: CompatSsoLoginListQuery$variables;
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
var v0 = [
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "count"
|
||||
},
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "cursor"
|
||||
},
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "id"
|
||||
}
|
||||
],
|
||||
v1 = [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "id",
|
||||
"variableName": "id"
|
||||
}
|
||||
],
|
||||
v2 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "__typename",
|
||||
"storageKey": null
|
||||
},
|
||||
v3 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
v4 = [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "after",
|
||||
"variableName": "cursor"
|
||||
},
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "first",
|
||||
"variableName": "count"
|
||||
}
|
||||
],
|
||||
v5 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "createdAt",
|
||||
"storageKey": null
|
||||
};
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "CompatSsoLoginListQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v1/*: any*/),
|
||||
"concreteType": null,
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"args": null,
|
||||
"kind": "FragmentSpread",
|
||||
"name": "CompatSsoLoginList_user"
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "RootQuery",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Operation",
|
||||
"name": "CompatSsoLoginListQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v1/*: any*/),
|
||||
"concreteType": null,
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v2/*: any*/),
|
||||
(v3/*: any*/),
|
||||
{
|
||||
"kind": "InlineFragment",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v4/*: any*/),
|
||||
"concreteType": "CompatSsoLoginConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "compatSsoLogins",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "CompatSsoLoginEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "CompatSsoLogin",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v3/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "redirectUri",
|
||||
"storageKey": null
|
||||
},
|
||||
(v5/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "CompatSession",
|
||||
"kind": "LinkedField",
|
||||
"name": "session",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v3/*: any*/),
|
||||
(v5/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "deviceId",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "finishedAt",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
(v2/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "cursor",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "PageInfo",
|
||||
"kind": "LinkedField",
|
||||
"name": "pageInfo",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "endCursor",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "hasNextPage",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v4/*: any*/),
|
||||
"filters": null,
|
||||
"handle": "connection",
|
||||
"key": "CompatSsoLoginList_user_compatSsoLogins",
|
||||
"kind": "LinkedHandle",
|
||||
"name": "compatSsoLogins"
|
||||
}
|
||||
],
|
||||
"type": "User",
|
||||
"abstractKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "45c6342d3a53a3e3b2b18617796cf654",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "CompatSsoLoginListQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query CompatSsoLoginListQuery(\n $count: Int\n $cursor: String\n $id: ID!\n) {\n node(id: $id) {\n __typename\n ...CompatSsoLoginList_user\n id\n }\n}\n\nfragment CompatSsoLoginList_user on User {\n compatSsoLogins(first: $count, after: $cursor) {\n edges {\n node {\n id\n ...CompatSsoLogin_login\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n id\n}\n\nfragment CompatSsoLogin_login on CompatSsoLogin {\n id\n redirectUri\n createdAt\n session {\n id\n createdAt\n deviceId\n finishedAt\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "cafc795d1bf9643ac6155c017e66c858";
|
||||
|
||||
export default node;
|
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<d3404a632e1928901a9a8ec12357528d>>
|
||||
* @generated SignedSource<<4ace8ea8668e3dc638df21400c690bd8>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -8,16 +8,18 @@
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { Fragment, ReaderFragment } from 'relay-runtime';
|
||||
import { ReaderFragment, RefetchableFragment } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type CompatSsoLoginList_user$data = {
|
||||
readonly compatSsoLogins: {
|
||||
readonly edges: ReadonlyArray<{
|
||||
readonly node: {
|
||||
readonly id: string;
|
||||
readonly " $fragmentSpreads": FragmentRefs<"CompatSsoLogin_login">;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
readonly id: string;
|
||||
readonly " $fragmentType": "CompatSsoLoginList_user";
|
||||
};
|
||||
export type CompatSsoLoginList_user$key = {
|
||||
@@ -25,24 +27,64 @@ export type CompatSsoLoginList_user$key = {
|
||||
readonly " $fragmentSpreads": FragmentRefs<"CompatSsoLoginList_user">;
|
||||
};
|
||||
|
||||
const node: ReaderFragment = {
|
||||
"argumentDefinitions": [],
|
||||
import CompatSsoLoginListQuery_graphql from './CompatSsoLoginListQuery.graphql';
|
||||
|
||||
const node: ReaderFragment = (function(){
|
||||
var v0 = [
|
||||
"compatSsoLogins"
|
||||
],
|
||||
v1 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
};
|
||||
return {
|
||||
"argumentDefinitions": [
|
||||
{
|
||||
"kind": "RootArgument",
|
||||
"name": "count"
|
||||
},
|
||||
{
|
||||
"kind": "RootArgument",
|
||||
"name": "cursor"
|
||||
}
|
||||
],
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"metadata": {
|
||||
"connection": [
|
||||
{
|
||||
"count": "count",
|
||||
"cursor": "cursor",
|
||||
"direction": "forward",
|
||||
"path": (v0/*: any*/)
|
||||
}
|
||||
],
|
||||
"refetch": {
|
||||
"connection": {
|
||||
"forward": {
|
||||
"count": "count",
|
||||
"cursor": "cursor"
|
||||
},
|
||||
"backward": null,
|
||||
"path": (v0/*: any*/)
|
||||
},
|
||||
"fragmentPathInResult": [
|
||||
"node"
|
||||
],
|
||||
"operation": CompatSsoLoginListQuery_graphql,
|
||||
"identifierField": "id"
|
||||
}
|
||||
},
|
||||
"name": "CompatSsoLoginList_user",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
"value": 10
|
||||
}
|
||||
],
|
||||
"alias": "compatSsoLogins",
|
||||
"args": null,
|
||||
"concreteType": "CompatSsoLoginConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "compatSsoLogins",
|
||||
"name": "__CompatSsoLoginList_user_compatSsoLogins_connection",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
@@ -61,25 +103,67 @@ const node: ReaderFragment = {
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v1/*: any*/),
|
||||
{
|
||||
"args": null,
|
||||
"kind": "FragmentSpread",
|
||||
"name": "CompatSsoLogin_login"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "__typename",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "cursor",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "PageInfo",
|
||||
"kind": "LinkedField",
|
||||
"name": "pageInfo",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "endCursor",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "hasNextPage",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": "compatSsoLogins(first:10)"
|
||||
}
|
||||
"storageKey": null
|
||||
},
|
||||
(v1/*: any*/)
|
||||
],
|
||||
"type": "User",
|
||||
"abstractKey": null
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "b70f4b63784afe8f1f69c78198194cc9";
|
||||
(node as any).hash = "cafc795d1bf9643ac6155c017e66c858";
|
||||
|
||||
export default node;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<bafb31541b97839f32ff9790773ff904>>
|
||||
* @generated SignedSource<<20e2b233e5154ea60632046abc2aa29a>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -11,8 +11,15 @@
|
||||
import { Fragment, ReaderFragment } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type CompatSsoLogin_login$data = {
|
||||
readonly createdAt: any;
|
||||
readonly id: string;
|
||||
readonly redirectUri: any;
|
||||
readonly session: {
|
||||
readonly createdAt: any;
|
||||
readonly deviceId: string;
|
||||
readonly finishedAt: any | null;
|
||||
readonly id: string;
|
||||
} | null;
|
||||
readonly " $fragmentType": "CompatSsoLogin_login";
|
||||
};
|
||||
export type CompatSsoLogin_login$key = {
|
||||
@@ -20,31 +27,69 @@ export type CompatSsoLogin_login$key = {
|
||||
readonly " $fragmentSpreads": FragmentRefs<"CompatSsoLogin_login">;
|
||||
};
|
||||
|
||||
const node: ReaderFragment = {
|
||||
const node: ReaderFragment = (function(){
|
||||
var v0 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
v1 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "createdAt",
|
||||
"storageKey": null
|
||||
};
|
||||
return {
|
||||
"argumentDefinitions": [],
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "CompatSsoLogin_login",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
(v0/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "redirectUri",
|
||||
"storageKey": null
|
||||
},
|
||||
(v1/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "CompatSession",
|
||||
"kind": "LinkedField",
|
||||
"name": "session",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v0/*: any*/),
|
||||
(v1/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "deviceId",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "finishedAt",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "CompatSsoLogin",
|
||||
"abstractKey": null
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "e1151a93f1ba4a56332b8aa6129f7bfe";
|
||||
(node as any).hash = "7be3b416b1023cea0de7a87b9738e5d5";
|
||||
|
||||
export default node;
|
||||
|
@@ -20,7 +20,7 @@ import type { HomeQuery } from "./__generated__/HomeQuery.graphql";
|
||||
const Home: React.FC = () => {
|
||||
const data = useLazyLoadQuery<HomeQuery>(
|
||||
graphql`
|
||||
query HomeQuery {
|
||||
query HomeQuery($count: Int!, $cursor: String) {
|
||||
currentUser {
|
||||
id
|
||||
username
|
||||
@@ -29,7 +29,7 @@ const Home: React.FC = () => {
|
||||
}
|
||||
}
|
||||
`,
|
||||
{}
|
||||
{ count: 2 }
|
||||
);
|
||||
|
||||
if (data.currentUser) {
|
||||
|
144
frontend/src/pages/__generated__/HomeQuery.graphql.ts
generated
144
frontend/src/pages/__generated__/HomeQuery.graphql.ts
generated
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @generated SignedSource<<94462aca9c48eae79c22a11003d865c3>>
|
||||
* @generated SignedSource<<874ab84c1095ab907f12b91b55f4bf2c>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
@@ -10,7 +10,10 @@
|
||||
|
||||
import { ConcreteRequest, Query } from 'relay-runtime';
|
||||
import { FragmentRefs } from "relay-runtime";
|
||||
export type HomeQuery$variables = {};
|
||||
export type HomeQuery$variables = {
|
||||
count: number;
|
||||
cursor?: string | null;
|
||||
};
|
||||
export type HomeQuery$data = {
|
||||
readonly currentUser: {
|
||||
readonly id: string;
|
||||
@@ -24,23 +27,54 @@ export type HomeQuery = {
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
var v0 = {
|
||||
var v0 = [
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "count"
|
||||
},
|
||||
{
|
||||
"defaultValue": null,
|
||||
"kind": "LocalArgument",
|
||||
"name": "cursor"
|
||||
}
|
||||
],
|
||||
v1 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
v1 = {
|
||||
v2 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "username",
|
||||
"storageKey": null
|
||||
},
|
||||
v3 = [
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "after",
|
||||
"variableName": "cursor"
|
||||
},
|
||||
{
|
||||
"kind": "Variable",
|
||||
"name": "first",
|
||||
"variableName": "count"
|
||||
}
|
||||
],
|
||||
v4 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "createdAt",
|
||||
"storageKey": null
|
||||
};
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": [],
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "HomeQuery",
|
||||
@@ -53,8 +87,8 @@ return {
|
||||
"name": "currentUser",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v0/*: any*/),
|
||||
(v1/*: any*/),
|
||||
(v2/*: any*/),
|
||||
{
|
||||
"args": null,
|
||||
"kind": "FragmentSpread",
|
||||
@@ -69,7 +103,7 @@ return {
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": [],
|
||||
"argumentDefinitions": (v0/*: any*/),
|
||||
"kind": "Operation",
|
||||
"name": "HomeQuery",
|
||||
"selections": [
|
||||
@@ -81,17 +115,11 @@ return {
|
||||
"name": "currentUser",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v0/*: any*/),
|
||||
(v1/*: any*/),
|
||||
(v2/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
"value": 10
|
||||
}
|
||||
],
|
||||
"args": (v3/*: any*/),
|
||||
"concreteType": "CompatSsoLoginConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "compatSsoLogins",
|
||||
@@ -113,22 +141,98 @@ return {
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v0/*: any*/),
|
||||
(v1/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "redirectUri",
|
||||
"storageKey": null
|
||||
},
|
||||
(v4/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "CompatSession",
|
||||
"kind": "LinkedField",
|
||||
"name": "session",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v1/*: any*/),
|
||||
(v4/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "deviceId",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "finishedAt",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "__typename",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "cursor",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "PageInfo",
|
||||
"kind": "LinkedField",
|
||||
"name": "pageInfo",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "endCursor",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "hasNextPage",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": "compatSsoLogins(first:10)"
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v3/*: any*/),
|
||||
"filters": null,
|
||||
"handle": "connection",
|
||||
"key": "CompatSsoLoginList_user_compatSsoLogins",
|
||||
"kind": "LinkedHandle",
|
||||
"name": "compatSsoLogins"
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
@@ -136,16 +240,16 @@ return {
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "1b4d3469bb6ccc19b8944b1f7fedd9c5",
|
||||
"cacheID": "3543c7ada63831383f66dbeed4b1648e",
|
||||
"id": null,
|
||||
"metadata": {},
|
||||
"name": "HomeQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query HomeQuery {\n currentUser {\n id\n username\n ...CompatSsoLoginList_user\n }\n}\n\nfragment CompatSsoLoginList_user on User {\n compatSsoLogins(first: 10) {\n edges {\n node {\n ...CompatSsoLogin_login\n id\n }\n }\n }\n}\n\nfragment CompatSsoLogin_login on CompatSsoLogin {\n id\n redirectUri\n}\n"
|
||||
"text": "query HomeQuery(\n $count: Int!\n $cursor: String\n) {\n currentUser {\n id\n username\n ...CompatSsoLoginList_user\n }\n}\n\nfragment CompatSsoLoginList_user on User {\n compatSsoLogins(first: $count, after: $cursor) {\n edges {\n node {\n id\n ...CompatSsoLogin_login\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n id\n}\n\nfragment CompatSsoLogin_login on CompatSsoLogin {\n id\n redirectUri\n createdAt\n session {\n id\n createdAt\n deviceId\n finishedAt\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "a5defd2dc81b62abebfe7a393573d5a8";
|
||||
(node as any).hash = "1cd5ce8ae5a912b3d7ecf0c6e3cd8469";
|
||||
|
||||
export default node;
|
||||
|
Reference in New Issue
Block a user