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
Merge the mas_graphql
crate into the mas_handlers
crate (#2783)
This commit is contained in:
26
Cargo.lock
generated
26
Cargo.lock
generated
@@ -3018,7 +3018,6 @@ dependencies = [
|
||||
"mas-config",
|
||||
"mas-data-model",
|
||||
"mas-email",
|
||||
"mas-graphql",
|
||||
"mas-handlers",
|
||||
"mas-http",
|
||||
"mas-i18n",
|
||||
@@ -3125,29 +3124,6 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mas-graphql"
|
||||
version = "0.9.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-graphql",
|
||||
"async-trait",
|
||||
"chrono",
|
||||
"lettre",
|
||||
"mas-data-model",
|
||||
"mas-matrix",
|
||||
"mas-policy",
|
||||
"mas-storage",
|
||||
"oauth2-types",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tower",
|
||||
"tracing",
|
||||
"ulid",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mas-handlers"
|
||||
version = "0.9.0"
|
||||
@@ -3155,6 +3131,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"argon2",
|
||||
"async-graphql",
|
||||
"async-trait",
|
||||
"axum",
|
||||
"axum-extra",
|
||||
"axum-macros",
|
||||
@@ -3170,7 +3147,6 @@ dependencies = [
|
||||
"lettre",
|
||||
"mas-axum-utils",
|
||||
"mas-data-model",
|
||||
"mas-graphql",
|
||||
"mas-http",
|
||||
"mas-i18n",
|
||||
"mas-iana",
|
||||
|
@@ -57,7 +57,6 @@ sentry-tower = { version = "0.31.8", features = ["http"] }
|
||||
mas-config.workspace = true
|
||||
mas-data-model.workspace = true
|
||||
mas-email.workspace = true
|
||||
mas-graphql.workspace = true
|
||||
mas-handlers = { workspace = true }
|
||||
mas-http = { workspace = true, features = ["client"] }
|
||||
mas-i18n.workspace = true
|
||||
|
@@ -22,7 +22,7 @@ use ipnetwork::IpNetwork;
|
||||
use mas_data_model::SiteConfig;
|
||||
use mas_handlers::{
|
||||
passwords::PasswordManager, ActivityTracker, BoundActivityTracker, CookieManager, ErrorWrapper,
|
||||
HttpClientFactory, MetadataCache,
|
||||
GraphQLSchema, HttpClientFactory, MetadataCache,
|
||||
};
|
||||
use mas_i18n::Translator;
|
||||
use mas_keystore::{Encrypter, Keystore};
|
||||
@@ -50,7 +50,7 @@ pub struct AppState {
|
||||
pub url_builder: UrlBuilder,
|
||||
pub homeserver_connection: SynapseConnection,
|
||||
pub policy_factory: Arc<PolicyFactory>,
|
||||
pub graphql_schema: mas_graphql::Schema,
|
||||
pub graphql_schema: GraphQLSchema,
|
||||
pub http_client_factory: HttpClientFactory,
|
||||
pub password_manager: PasswordManager,
|
||||
pub metadata_cache: MetadataCache,
|
||||
@@ -144,7 +144,7 @@ impl FromRef<AppState> for PgPool {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRef<AppState> for mas_graphql::Schema {
|
||||
impl FromRef<AppState> for GraphQLSchema {
|
||||
fn from_ref(input: &AppState) -> Self {
|
||||
input.graphql_schema.clone()
|
||||
}
|
||||
|
@@ -1,36 +0,0 @@
|
||||
[package]
|
||||
name = "mas-graphql"
|
||||
version.workspace = true
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
publish = false
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
async-graphql.workspace = true
|
||||
async-trait.workspace = true
|
||||
chrono.workspace = true
|
||||
lettre.workspace = true
|
||||
serde.workspace = true
|
||||
thiserror.workspace = true
|
||||
tokio.workspace = true
|
||||
tracing.workspace = true
|
||||
tower.workspace = true
|
||||
ulid.workspace = true
|
||||
url.workspace = true
|
||||
|
||||
oauth2-types.workspace = true
|
||||
mas-data-model.workspace = true
|
||||
mas-matrix.workspace = true
|
||||
mas-policy.workspace = true
|
||||
mas-storage.workspace = true
|
||||
|
||||
[[bin]]
|
||||
name = "schema"
|
||||
doc = false
|
@@ -1,174 +0,0 @@
|
||||
// Copyright 2022-2023 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.
|
||||
|
||||
#![deny(clippy::future_not_send)]
|
||||
#![allow(clippy::module_name_repetitions, clippy::unused_async)]
|
||||
|
||||
use async_graphql::EmptySubscription;
|
||||
use mas_data_model::{BrowserSession, Session, User};
|
||||
use ulid::Ulid;
|
||||
|
||||
mod model;
|
||||
mod mutations;
|
||||
mod query;
|
||||
mod state;
|
||||
|
||||
pub use self::{
|
||||
model::{CreationEvent, Node},
|
||||
mutations::Mutation,
|
||||
query::Query,
|
||||
state::{BoxState, State},
|
||||
};
|
||||
|
||||
pub type Schema = async_graphql::Schema<Query, Mutation, EmptySubscription>;
|
||||
pub type SchemaBuilder = async_graphql::SchemaBuilder<Query, Mutation, EmptySubscription>;
|
||||
|
||||
#[must_use]
|
||||
pub fn schema_builder() -> SchemaBuilder {
|
||||
async_graphql::Schema::build(Query::new(), Mutation::new(), EmptySubscription)
|
||||
.register_output_type::<Node>()
|
||||
.register_output_type::<CreationEvent>()
|
||||
}
|
||||
|
||||
/// The identity of the requester.
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
||||
pub enum Requester {
|
||||
/// The requester presented no authentication information.
|
||||
#[default]
|
||||
Anonymous,
|
||||
|
||||
/// The requester is a browser session, stored in a cookie.
|
||||
BrowserSession(Box<BrowserSession>),
|
||||
|
||||
/// The requester is a `OAuth2` session, with an access token.
|
||||
OAuth2Session(Box<(Session, Option<User>)>),
|
||||
}
|
||||
|
||||
trait OwnerId {
|
||||
fn owner_id(&self) -> Option<Ulid>;
|
||||
}
|
||||
|
||||
impl OwnerId for User {
|
||||
fn owner_id(&self) -> Option<Ulid> {
|
||||
Some(self.id)
|
||||
}
|
||||
}
|
||||
|
||||
impl OwnerId for BrowserSession {
|
||||
fn owner_id(&self) -> Option<Ulid> {
|
||||
Some(self.user.id)
|
||||
}
|
||||
}
|
||||
|
||||
impl OwnerId for mas_data_model::UserEmail {
|
||||
fn owner_id(&self) -> Option<Ulid> {
|
||||
Some(self.user_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl OwnerId for Session {
|
||||
fn owner_id(&self) -> Option<Ulid> {
|
||||
self.user_id
|
||||
}
|
||||
}
|
||||
|
||||
impl OwnerId for mas_data_model::CompatSession {
|
||||
fn owner_id(&self) -> Option<Ulid> {
|
||||
Some(self.user_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl OwnerId for mas_data_model::UpstreamOAuthLink {
|
||||
fn owner_id(&self) -> Option<Ulid> {
|
||||
self.user_id
|
||||
}
|
||||
}
|
||||
|
||||
/// A dumb wrapper around a `Ulid` to implement `OwnerId` for it.
|
||||
pub struct UserId(Ulid);
|
||||
|
||||
impl OwnerId for UserId {
|
||||
fn owner_id(&self) -> Option<Ulid> {
|
||||
Some(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Requester {
|
||||
fn browser_session(&self) -> Option<&BrowserSession> {
|
||||
match self {
|
||||
Self::BrowserSession(session) => Some(session),
|
||||
Self::OAuth2Session(_) | Self::Anonymous => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn user(&self) -> Option<&User> {
|
||||
match self {
|
||||
Self::BrowserSession(session) => Some(&session.user),
|
||||
Self::OAuth2Session(tuple) => tuple.1.as_ref(),
|
||||
Self::Anonymous => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn oauth2_session(&self) -> Option<&Session> {
|
||||
match self {
|
||||
Self::OAuth2Session(tuple) => Some(&tuple.0),
|
||||
Self::BrowserSession(_) | Self::Anonymous => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the requester can access the resource.
|
||||
fn is_owner_or_admin(&self, resource: &impl OwnerId) -> bool {
|
||||
// If the requester is an admin, they can do anything.
|
||||
if self.is_admin() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, they must be the owner of the resource.
|
||||
let Some(owner_id) = resource.owner_id() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let Some(user) = self.user() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
user.id == owner_id
|
||||
}
|
||||
|
||||
fn is_admin(&self) -> bool {
|
||||
match self {
|
||||
Self::OAuth2Session(tuple) => {
|
||||
// TODO: is this the right scope?
|
||||
// This has to be in sync with the policy
|
||||
tuple.0.scope.contains("urn:mas:admin")
|
||||
}
|
||||
Self::BrowserSession(_) | Self::Anonymous => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BrowserSession> for Requester {
|
||||
fn from(session: BrowserSession) -> Self {
|
||||
Self::BrowserSession(Box::new(session))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Option<T>> for Requester
|
||||
where
|
||||
T: Into<Requester>,
|
||||
{
|
||||
fn from(session: Option<T>) -> Self {
|
||||
session.map(Into::into).unwrap_or_default()
|
||||
}
|
||||
}
|
@@ -15,6 +15,7 @@ workspace = true
|
||||
# Async runtime
|
||||
tokio.workspace = true
|
||||
futures-util = "0.3.30"
|
||||
async-trait.workspace = true
|
||||
|
||||
# Logging and tracing
|
||||
tracing.workspace = true
|
||||
@@ -70,7 +71,6 @@ ulid.workspace = true
|
||||
|
||||
mas-axum-utils.workspace = true
|
||||
mas-data-model.workspace = true
|
||||
mas-graphql.workspace = true
|
||||
mas-http.workspace = true
|
||||
mas-i18n.workspace = true
|
||||
mas-iana.workspace = true
|
||||
|
@@ -22,6 +22,6 @@
|
||||
#![warn(clippy::pedantic)]
|
||||
|
||||
fn main() {
|
||||
let schema = mas_graphql::schema_builder().finish();
|
||||
let schema = mas_handlers::graphql_schema_builder().finish();
|
||||
println!("{}", schema.sdl());
|
||||
}
|
@@ -12,15 +12,18 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#![allow(clippy::module_name_repetitions)]
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_graphql::{
|
||||
extensions::Tracing,
|
||||
http::{playground_source, GraphQLPlaygroundConfig, MultipartOptions},
|
||||
EmptySubscription,
|
||||
};
|
||||
use axum::{
|
||||
async_trait,
|
||||
extract::{BodyStream, RawQuery, State},
|
||||
extract::{BodyStream, RawQuery, State as AxumState},
|
||||
http::StatusCode,
|
||||
response::{Html, IntoResponse, Response},
|
||||
Json, TypedHeader,
|
||||
@@ -31,8 +34,7 @@ use hyper::header::CACHE_CONTROL;
|
||||
use mas_axum_utils::{
|
||||
cookies::CookieJar, sentry::SentryEventID, FancyError, SessionInfo, SessionInfoExt,
|
||||
};
|
||||
use mas_data_model::{SiteConfig, User};
|
||||
use mas_graphql::{Requester, Schema};
|
||||
use mas_data_model::{BrowserSession, Session, SiteConfig, User};
|
||||
use mas_matrix::HomeserverConnection;
|
||||
use mas_policy::{InstantiateError, Policy, PolicyFactory};
|
||||
use mas_storage::{
|
||||
@@ -44,7 +46,19 @@ use rand::{thread_rng, SeedableRng};
|
||||
use rand_chacha::ChaChaRng;
|
||||
use sqlx::PgPool;
|
||||
use tracing::{info_span, Instrument};
|
||||
use ulid::Ulid;
|
||||
|
||||
mod model;
|
||||
mod mutations;
|
||||
mod query;
|
||||
mod state;
|
||||
|
||||
pub use self::state::{BoxState, State};
|
||||
use self::{
|
||||
model::{CreationEvent, Node},
|
||||
mutations::Mutation,
|
||||
query::Query,
|
||||
};
|
||||
use crate::{impl_from_error_for_route, BoundActivityTracker};
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -58,7 +72,7 @@ struct GraphQLState {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl mas_graphql::State for GraphQLState {
|
||||
impl state::State for GraphQLState {
|
||||
async fn repository(&self) -> Result<BoxRepository, RepositoryError> {
|
||||
let repo = PgRepository::from_pool(&self.pool)
|
||||
.await
|
||||
@@ -106,12 +120,9 @@ pub fn schema(
|
||||
homeserver_connection: Arc::new(homeserver_connection),
|
||||
site_config,
|
||||
};
|
||||
let state: mas_graphql::BoxState = Box::new(state);
|
||||
let state: BoxState = Box::new(state);
|
||||
|
||||
mas_graphql::schema_builder()
|
||||
.extension(Tracing)
|
||||
.data(state)
|
||||
.finish()
|
||||
schema_builder().extension(Tracing).data(state).finish()
|
||||
}
|
||||
|
||||
fn span_for_graphql_request(request: &async_graphql::Request) -> tracing::Span {
|
||||
@@ -261,7 +272,7 @@ async fn get_requester(
|
||||
}
|
||||
|
||||
pub async fn post(
|
||||
State(schema): State<Schema>,
|
||||
AxumState(schema): AxumState<Schema>,
|
||||
clock: BoxClock,
|
||||
repo: BoxRepository,
|
||||
activity_tracker: BoundActivityTracker,
|
||||
@@ -302,7 +313,7 @@ pub async fn post(
|
||||
}
|
||||
|
||||
pub async fn get(
|
||||
State(schema): State<Schema>,
|
||||
AxumState(schema): AxumState<Schema>,
|
||||
clock: BoxClock,
|
||||
repo: BoxRepository,
|
||||
activity_tracker: BoundActivityTracker,
|
||||
@@ -338,3 +349,145 @@ pub async fn playground() -> impl IntoResponse {
|
||||
GraphQLPlaygroundConfig::new("/graphql").with_setting("request.credentials", "include"),
|
||||
))
|
||||
}
|
||||
|
||||
pub type Schema = async_graphql::Schema<Query, Mutation, EmptySubscription>;
|
||||
pub type SchemaBuilder = async_graphql::SchemaBuilder<Query, Mutation, EmptySubscription>;
|
||||
|
||||
#[must_use]
|
||||
pub fn schema_builder() -> SchemaBuilder {
|
||||
async_graphql::Schema::build(Query::new(), Mutation::new(), EmptySubscription)
|
||||
.register_output_type::<Node>()
|
||||
.register_output_type::<CreationEvent>()
|
||||
}
|
||||
|
||||
/// The identity of the requester.
|
||||
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
||||
pub enum Requester {
|
||||
/// The requester presented no authentication information.
|
||||
#[default]
|
||||
Anonymous,
|
||||
|
||||
/// The requester is a browser session, stored in a cookie.
|
||||
BrowserSession(Box<BrowserSession>),
|
||||
|
||||
/// The requester is a `OAuth2` session, with an access token.
|
||||
OAuth2Session(Box<(Session, Option<User>)>),
|
||||
}
|
||||
|
||||
trait OwnerId {
|
||||
fn owner_id(&self) -> Option<Ulid>;
|
||||
}
|
||||
|
||||
impl OwnerId for User {
|
||||
fn owner_id(&self) -> Option<Ulid> {
|
||||
Some(self.id)
|
||||
}
|
||||
}
|
||||
|
||||
impl OwnerId for BrowserSession {
|
||||
fn owner_id(&self) -> Option<Ulid> {
|
||||
Some(self.user.id)
|
||||
}
|
||||
}
|
||||
|
||||
impl OwnerId for mas_data_model::UserEmail {
|
||||
fn owner_id(&self) -> Option<Ulid> {
|
||||
Some(self.user_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl OwnerId for Session {
|
||||
fn owner_id(&self) -> Option<Ulid> {
|
||||
self.user_id
|
||||
}
|
||||
}
|
||||
|
||||
impl OwnerId for mas_data_model::CompatSession {
|
||||
fn owner_id(&self) -> Option<Ulid> {
|
||||
Some(self.user_id)
|
||||
}
|
||||
}
|
||||
|
||||
impl OwnerId for mas_data_model::UpstreamOAuthLink {
|
||||
fn owner_id(&self) -> Option<Ulid> {
|
||||
self.user_id
|
||||
}
|
||||
}
|
||||
|
||||
/// A dumb wrapper around a `Ulid` to implement `OwnerId` for it.
|
||||
pub struct UserId(Ulid);
|
||||
|
||||
impl OwnerId for UserId {
|
||||
fn owner_id(&self) -> Option<Ulid> {
|
||||
Some(self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Requester {
|
||||
fn browser_session(&self) -> Option<&BrowserSession> {
|
||||
match self {
|
||||
Self::BrowserSession(session) => Some(session),
|
||||
Self::OAuth2Session(_) | Self::Anonymous => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn user(&self) -> Option<&User> {
|
||||
match self {
|
||||
Self::BrowserSession(session) => Some(&session.user),
|
||||
Self::OAuth2Session(tuple) => tuple.1.as_ref(),
|
||||
Self::Anonymous => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn oauth2_session(&self) -> Option<&Session> {
|
||||
match self {
|
||||
Self::OAuth2Session(tuple) => Some(&tuple.0),
|
||||
Self::BrowserSession(_) | Self::Anonymous => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the requester can access the resource.
|
||||
fn is_owner_or_admin(&self, resource: &impl OwnerId) -> bool {
|
||||
// If the requester is an admin, they can do anything.
|
||||
if self.is_admin() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, they must be the owner of the resource.
|
||||
let Some(owner_id) = resource.owner_id() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let Some(user) = self.user() else {
|
||||
return false;
|
||||
};
|
||||
|
||||
user.id == owner_id
|
||||
}
|
||||
|
||||
fn is_admin(&self) -> bool {
|
||||
match self {
|
||||
Self::OAuth2Session(tuple) => {
|
||||
// TODO: is this the right scope?
|
||||
// This has to be in sync with the policy
|
||||
tuple.0.scope.contains("urn:mas:admin")
|
||||
}
|
||||
Self::BrowserSession(_) | Self::Anonymous => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BrowserSession> for Requester {
|
||||
fn from(session: BrowserSession) -> Self {
|
||||
Self::BrowserSession(Box::new(session))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Option<T>> for Requester
|
||||
where
|
||||
T: Into<Requester>,
|
||||
{
|
||||
fn from(session: Option<T>) -> Self {
|
||||
session.map(Into::into).unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@ use super::{
|
||||
AppSession, CompatSession, Cursor, NodeCursor, NodeType, OAuth2Session, PreloadedTotalCount,
|
||||
SessionState, User, UserAgent,
|
||||
};
|
||||
use crate::state::ContextExt;
|
||||
use crate::graphql::state::ContextExt;
|
||||
|
||||
/// A browser session represents a logged in user in a browser.
|
||||
#[derive(Description)]
|
@@ -19,7 +19,7 @@ use mas_storage::{compat::CompatSessionRepository, user::UserRepository};
|
||||
use url::Url;
|
||||
|
||||
use super::{BrowserSession, NodeType, SessionState, User, UserAgent};
|
||||
use crate::state::ContextExt;
|
||||
use crate::graphql::state::ContextExt;
|
||||
|
||||
/// Lazy-loaded reverse reference.
|
||||
///
|
@@ -21,7 +21,7 @@ use ulid::Ulid;
|
||||
use url::Url;
|
||||
|
||||
use super::{BrowserSession, NodeType, SessionState, User, UserAgent};
|
||||
use crate::{state::ContextExt, UserId};
|
||||
use crate::graphql::{state::ContextExt, UserId};
|
||||
|
||||
/// An OAuth 2.0 session represents a client session which used the OAuth APIs
|
||||
/// to login.
|
@@ -18,7 +18,7 @@ use chrono::{DateTime, Utc};
|
||||
use mas_storage::{upstream_oauth2::UpstreamOAuthProviderRepository, user::UserRepository};
|
||||
|
||||
use super::{NodeType, User};
|
||||
use crate::state::ContextExt;
|
||||
use crate::graphql::state::ContextExt;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UpstreamOAuth2Provider {
|
@@ -34,7 +34,7 @@ use super::{
|
||||
BrowserSession, CompatSession, Cursor, NodeCursor, NodeType, OAuth2Session,
|
||||
PreloadedTotalCount, SessionState, UpstreamOAuth2Link,
|
||||
};
|
||||
use crate::state::ContextExt;
|
||||
use crate::graphql::state::ContextExt;
|
||||
|
||||
#[derive(Description)]
|
||||
/// A user is an individual's account.
|
@@ -14,7 +14,7 @@
|
||||
|
||||
use async_graphql::Union;
|
||||
|
||||
use crate::model::{BrowserSession, OAuth2Session, User};
|
||||
use crate::graphql::model::{BrowserSession, OAuth2Session, User};
|
||||
|
||||
mod anonymous;
|
||||
pub use self::anonymous::Anonymous;
|
@@ -15,7 +15,7 @@
|
||||
use async_graphql::{Context, Enum, InputObject, Object, ID};
|
||||
use mas_storage::RepositoryAccess;
|
||||
|
||||
use crate::{
|
||||
use crate::graphql::{
|
||||
model::{BrowserSession, NodeType},
|
||||
state::ContextExt,
|
||||
};
|
@@ -20,7 +20,7 @@ use mas_storage::{
|
||||
RepositoryAccess,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
use crate::graphql::{
|
||||
model::{CompatSession, NodeType},
|
||||
state::ContextExt,
|
||||
};
|
@@ -15,7 +15,7 @@
|
||||
use anyhow::Context as _;
|
||||
use async_graphql::{Context, Description, Enum, InputObject, Object, ID};
|
||||
|
||||
use crate::{
|
||||
use crate::graphql::{
|
||||
model::{NodeType, User},
|
||||
state::ContextExt,
|
||||
UserId,
|
@@ -27,7 +27,7 @@ use mas_storage::{
|
||||
};
|
||||
use oauth2_types::scope::Scope;
|
||||
|
||||
use crate::{
|
||||
use crate::graphql::{
|
||||
model::{NodeType, OAuth2Session},
|
||||
state::ContextExt,
|
||||
};
|
@@ -20,7 +20,7 @@ use mas_storage::{
|
||||
};
|
||||
use tracing::{info, warn};
|
||||
|
||||
use crate::{
|
||||
use crate::graphql::{
|
||||
model::{NodeType, User},
|
||||
state::ContextExt,
|
||||
UserId,
|
@@ -20,7 +20,7 @@ use mas_storage::{
|
||||
RepositoryAccess,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
use crate::graphql::{
|
||||
model::{NodeType, User, UserEmail},
|
||||
state::ContextExt,
|
||||
UserId,
|
@@ -15,7 +15,7 @@
|
||||
use async_graphql::{Context, MergedObject, Object, ID};
|
||||
use mas_storage::user::UserRepository;
|
||||
|
||||
use crate::{
|
||||
use crate::graphql::{
|
||||
model::{
|
||||
Anonymous, BrowserSession, CompatSession, Node, NodeType, OAuth2Client, OAuth2Session,
|
||||
SiteConfig, User, UserEmail,
|
||||
@@ -234,7 +234,7 @@ impl BaseQuery {
|
||||
return Ok(Some(Node::Anonymous(Box::new(Anonymous))));
|
||||
}
|
||||
|
||||
if id.as_str() == crate::model::SITE_CONFIG_ID {
|
||||
if id.as_str() == crate::graphql::model::SITE_CONFIG_ID {
|
||||
return Ok(Some(Node::SiteConfig(Box::new(SiteConfig::new(
|
||||
ctx.state().site_config(),
|
||||
)))));
|
@@ -21,7 +21,7 @@ use mas_storage::{
|
||||
};
|
||||
use oauth2_types::scope::Scope;
|
||||
|
||||
use crate::{
|
||||
use crate::graphql::{
|
||||
model::{CompatSession, NodeType, OAuth2Session},
|
||||
state::ContextExt,
|
||||
UserId,
|
@@ -18,7 +18,7 @@ use async_graphql::{
|
||||
};
|
||||
use mas_storage::{upstream_oauth2::UpstreamOAuthProviderFilter, Pagination, RepositoryAccess};
|
||||
|
||||
use crate::{
|
||||
use crate::graphql::{
|
||||
model::{
|
||||
Cursor, NodeCursor, NodeType, PreloadedTotalCount, UpstreamOAuth2Link,
|
||||
UpstreamOAuth2Provider,
|
@@ -14,7 +14,7 @@
|
||||
|
||||
use async_graphql::{Context, Object};
|
||||
|
||||
use crate::{
|
||||
use crate::graphql::{
|
||||
model::{Viewer, ViewerSession},
|
||||
state::ContextExt,
|
||||
Requester,
|
@@ -17,7 +17,7 @@ use mas_matrix::HomeserverConnection;
|
||||
use mas_policy::Policy;
|
||||
use mas_storage::{BoxClock, BoxRepository, BoxRng, RepositoryError};
|
||||
|
||||
use crate::Requester;
|
||||
use crate::graphql::Requester;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
pub trait State {
|
@@ -90,7 +90,9 @@ pub use mas_axum_utils::{
|
||||
|
||||
pub use self::{
|
||||
activity_tracker::{ActivityTracker, Bound as BoundActivityTracker},
|
||||
graphql::schema as graphql_schema,
|
||||
graphql::{
|
||||
schema as graphql_schema, schema_builder as graphql_schema_builder, Schema as GraphQLSchema,
|
||||
},
|
||||
preferred_language::PreferredLanguage,
|
||||
upstream_oauth2::cache::MetadataCache,
|
||||
};
|
||||
@@ -110,7 +112,7 @@ where
|
||||
<B as HttpBody>::Data: Into<Bytes>,
|
||||
<B as HttpBody>::Error: std::error::Error + Send + Sync,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
mas_graphql::Schema: FromRef<S>,
|
||||
graphql::Schema: FromRef<S>,
|
||||
BoundActivityTracker: FromRequestParts<S>,
|
||||
BoxRepository: FromRequestParts<S>,
|
||||
BoxClock: FromRequestParts<S>,
|
||||
|
@@ -54,6 +54,7 @@ use tower::{Layer, Service, ServiceExt};
|
||||
use url::Url;
|
||||
|
||||
use crate::{
|
||||
graphql,
|
||||
passwords::{Hasher, PasswordManager},
|
||||
upstream_oauth2::cache::MetadataCache,
|
||||
ActivityTracker, BoundActivityTracker,
|
||||
@@ -102,7 +103,7 @@ pub(crate) struct TestState {
|
||||
pub url_builder: UrlBuilder,
|
||||
pub homeserver_connection: Arc<MockHomeserverConnection>,
|
||||
pub policy_factory: Arc<PolicyFactory>,
|
||||
pub graphql_schema: mas_graphql::Schema,
|
||||
pub graphql_schema: graphql::Schema,
|
||||
pub http_client_factory: HttpClientFactory,
|
||||
pub password_manager: PasswordManager,
|
||||
pub site_config: SiteConfig,
|
||||
@@ -198,9 +199,9 @@ impl TestState {
|
||||
rng: Arc::clone(&rng),
|
||||
clock: Arc::clone(&clock),
|
||||
};
|
||||
let state: mas_graphql::BoxState = Box::new(graphql_state);
|
||||
let state: crate::graphql::BoxState = Box::new(graphql_state);
|
||||
|
||||
let graphql_schema = mas_graphql::schema_builder().data(state).finish();
|
||||
let graphql_schema = graphql::schema_builder().data(state).finish();
|
||||
|
||||
let activity_tracker =
|
||||
ActivityTracker::new(pool.clone(), std::time::Duration::from_secs(1));
|
||||
@@ -316,7 +317,7 @@ struct TestGraphQLState {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl mas_graphql::State for TestGraphQLState {
|
||||
impl graphql::State for TestGraphQLState {
|
||||
async fn repository(&self) -> Result<BoxRepository, mas_storage::RepositoryError> {
|
||||
let repo = PgRepository::from_pool(&self.pool)
|
||||
.await
|
||||
@@ -356,7 +357,7 @@ impl FromRef<TestState> for PgPool {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRef<TestState> for mas_graphql::Schema {
|
||||
impl FromRef<TestState> for graphql::Schema {
|
||||
fn from_ref(input: &TestState) -> Self {
|
||||
input.graphql_schema.clone()
|
||||
}
|
||||
|
@@ -10,7 +10,7 @@ POLICIES_SCHEMA="${BASE_DIR}/policies/schema/"
|
||||
|
||||
set -x
|
||||
cargo run -p mas-config > "${CONFIG_SCHEMA}"
|
||||
cargo run -p mas-graphql > "${GRAPHQL_SCHEMA}"
|
||||
cargo run -p mas-handlers --bin graphql-schema > "${GRAPHQL_SCHEMA}"
|
||||
cargo run -p mas-i18n-scan -- --update "${BASE_DIR}/templates/" "${BASE_DIR}/translations/en.json"
|
||||
OUT_DIR="${POLICIES_SCHEMA}" cargo run -p mas-policy --features jsonschema
|
||||
|
||||
|
Reference in New Issue
Block a user