Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional fields in the GraphQL API for upstream providers #3687

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/cli/src/commands/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ impl Options {
homeserver_connection.clone(),
site_config.clone(),
password_manager.clone(),
url_builder.clone(),
);

let state = {
Expand Down
8 changes: 8 additions & 0 deletions crates/handlers/src/graphql/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use mas_axum_utils::{
use mas_data_model::{BrowserSession, Session, SiteConfig, User};
use mas_matrix::HomeserverConnection;
use mas_policy::{InstantiateError, Policy, PolicyFactory};
use mas_router::UrlBuilder;
use mas_storage::{BoxClock, BoxRepository, BoxRng, Clock, RepositoryError, SystemClock};
use mas_storage_pg::PgRepository;
use opentelemetry_semantic_conventions::trace::{GRAPHQL_DOCUMENT, GRAPHQL_OPERATION_NAME};
Expand Down Expand Up @@ -70,6 +71,7 @@ struct GraphQLState {
policy_factory: Arc<PolicyFactory>,
site_config: SiteConfig,
password_manager: PasswordManager,
url_builder: UrlBuilder,
}

#[async_trait]
Expand Down Expand Up @@ -98,6 +100,10 @@ impl state::State for GraphQLState {
self.homeserver_connection.as_ref()
}

fn url_builder(&self) -> &UrlBuilder {
&self.url_builder
}

fn clock(&self) -> BoxClock {
let clock = SystemClock::default();
Box::new(clock)
Expand All @@ -119,13 +125,15 @@ pub fn schema(
homeserver_connection: impl HomeserverConnection<Error = anyhow::Error> + 'static,
site_config: SiteConfig,
password_manager: PasswordManager,
url_builder: UrlBuilder,
) -> Schema {
let state = GraphQLState {
pool: pool.clone(),
policy_factory: Arc::clone(policy_factory),
homeserver_connection: Arc::new(homeserver_connection),
site_config,
password_manager,
url_builder,
};
let state: BoxState = Box::new(state);

Expand Down
26 changes: 26 additions & 0 deletions crates/handlers/src/graphql/model/upstream_oauth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use anyhow::Context as _;
use async_graphql::{Context, Object, ID};
use chrono::{DateTime, Utc};
use mas_storage::{upstream_oauth2::UpstreamOAuthProviderRepository, user::UserRepository};
use url::Url;

use super::{NodeType, User};
use crate::graphql::state::ContextExt;
Expand Down Expand Up @@ -45,6 +46,26 @@ impl UpstreamOAuth2Provider {
pub async fn client_id(&self) -> &str {
&self.provider.client_id
}

/// A human-readable name for this provider.
pub async fn human_name(&self) -> Option<&str> {
self.provider.human_name.as_deref()
}

/// A brand identifier for this provider.
///
/// One of `google`, `github`, `gitlab`, `apple` or `facebook`.
pub async fn brand_name(&self) -> Option<&str> {
self.provider.brand_name.as_deref()
}

/// URL to start the linking process of the current user with this provider.
pub async fn link_url(&self, context: &Context<'_>) -> Url {
let state = context.state();
let url_builder = state.url_builder();
let route = mas_router::UpstreamOAuth2Authorize::new(self.provider.id);
url_builder.absolute_url_for(&route)
}
}

impl UpstreamOAuth2Link {
Expand Down Expand Up @@ -82,6 +103,11 @@ impl UpstreamOAuth2Link {
&self.link.subject
}

/// A human-readable name for the link subject.
pub async fn human_account_name(&self) -> Option<&str> {
self.link.human_account_name.as_deref()
}

/// The provider for which this link is.
pub async fn provider(
&self,
Expand Down
2 changes: 2 additions & 0 deletions crates/handlers/src/graphql/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use mas_data_model::SiteConfig;
use mas_matrix::HomeserverConnection;
use mas_policy::Policy;
use mas_router::UrlBuilder;
use mas_storage::{BoxClock, BoxRepository, BoxRng, RepositoryError};

use crate::{graphql::Requester, passwords::PasswordManager};
Expand All @@ -20,6 +21,7 @@ pub trait State {
fn clock(&self) -> BoxClock;
fn rng(&self) -> BoxRng;
fn site_config(&self) -> &SiteConfig;
fn url_builder(&self) -> &UrlBuilder;
}

pub type BoxState = Box<dyn State + Send + Sync + 'static>;
Expand Down
6 changes: 6 additions & 0 deletions crates/handlers/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ impl TestState {
rng: Arc::clone(&rng),
clock: Arc::clone(&clock),
password_manager: password_manager.clone(),
url_builder: url_builder.clone(),
};
let state: crate::graphql::BoxState = Box::new(graphql_state);

Expand Down Expand Up @@ -370,6 +371,7 @@ struct TestGraphQLState {
clock: Arc<MockClock>,
rng: Arc<Mutex<ChaChaRng>>,
password_manager: PasswordManager,
url_builder: UrlBuilder,
}

#[async_trait]
Expand All @@ -394,6 +396,10 @@ impl graphql::State for TestGraphQLState {
&self.homeserver_connection
}

fn url_builder(&self) -> &UrlBuilder {
&self.url_builder
}

fn clock(&self) -> BoxClock {
Box::new(self.clock.clone())
}
Expand Down
18 changes: 18 additions & 0 deletions frontend/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -1535,6 +1535,10 @@ type UpstreamOAuth2Link implements Node & CreationEvent {
"""
subject: String!
"""
A human-readable name for the link subject.
"""
humanAccountName: String
"""
The provider for which this link is.
"""
provider: UpstreamOAuth2Provider!
Expand Down Expand Up @@ -1594,6 +1598,20 @@ type UpstreamOAuth2Provider implements Node & CreationEvent {
Client ID used for this provider.
"""
clientId: String!
"""
A human-readable name for this provider.
"""
humanName: String
"""
A brand identifier for this provider.
One of `google`, `github`, `gitlab`, `apple` or `facebook`.
"""
brandName: String
"""
URL to start the linking process of the current user with this provider.
"""
linkUrl: Url!
}

type UpstreamOAuth2ProviderConnection {
Expand Down
12 changes: 12 additions & 0 deletions frontend/src/gql/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1116,6 +1116,8 @@ export type UpstreamOAuth2Link = CreationEvent & Node & {
__typename?: 'UpstreamOAuth2Link';
/** When the object was created. */
createdAt: Scalars['DateTime']['output'];
/** A human-readable name for the link subject. */
humanAccountName?: Maybe<Scalars['String']['output']>;
/** ID of the object. */
id: Scalars['ID']['output'];
/** The provider for which this link is. */
Expand Down Expand Up @@ -1149,14 +1151,24 @@ export type UpstreamOAuth2LinkEdge = {

export type UpstreamOAuth2Provider = CreationEvent & Node & {
__typename?: 'UpstreamOAuth2Provider';
/**
* A brand identifier for this provider.
*
* One of `google`, `github`, `gitlab`, `apple` or `facebook`.
*/
brandName?: Maybe<Scalars['String']['output']>;
/** Client ID used for this provider. */
clientId: Scalars['String']['output'];
/** When the object was created. */
createdAt: Scalars['DateTime']['output'];
/** A human-readable name for this provider. */
humanName?: Maybe<Scalars['String']['output']>;
/** ID of the object. */
id: Scalars['ID']['output'];
/** OpenID Connect issuer URL. */
issuer?: Maybe<Scalars['String']['output']>;
/** URL to start the linking process of the current user with this provider. */
linkUrl: Scalars['Url']['output'];
};

export type UpstreamOAuth2ProviderConnection = {
Expand Down
Loading