Skip to content

Commit b5940b9

Browse files
committed
Additional fields in the GraphQL API for upstream providers
1 parent ac7c9dd commit b5940b9

File tree

7 files changed

+73
-0
lines changed

7 files changed

+73
-0
lines changed

crates/cli/src/commands/server.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ impl Options {
208208
homeserver_connection.clone(),
209209
site_config.clone(),
210210
password_manager.clone(),
211+
url_builder.clone(),
211212
);
212213

213214
let state = {

crates/handlers/src/graphql/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use mas_axum_utils::{
3232
use mas_data_model::{BrowserSession, Session, SiteConfig, User};
3333
use mas_matrix::HomeserverConnection;
3434
use mas_policy::{InstantiateError, Policy, PolicyFactory};
35+
use mas_router::UrlBuilder;
3536
use mas_storage::{BoxClock, BoxRepository, BoxRng, Clock, RepositoryError, SystemClock};
3637
use mas_storage_pg::PgRepository;
3738
use opentelemetry_semantic_conventions::trace::{GRAPHQL_DOCUMENT, GRAPHQL_OPERATION_NAME};
@@ -70,6 +71,7 @@ struct GraphQLState {
7071
policy_factory: Arc<PolicyFactory>,
7172
site_config: SiteConfig,
7273
password_manager: PasswordManager,
74+
url_builder: UrlBuilder,
7375
}
7476

7577
#[async_trait]
@@ -98,6 +100,10 @@ impl state::State for GraphQLState {
98100
self.homeserver_connection.as_ref()
99101
}
100102

103+
fn url_builder(&self) -> &UrlBuilder {
104+
&self.url_builder
105+
}
106+
101107
fn clock(&self) -> BoxClock {
102108
let clock = SystemClock::default();
103109
Box::new(clock)
@@ -119,13 +125,15 @@ pub fn schema(
119125
homeserver_connection: impl HomeserverConnection<Error = anyhow::Error> + 'static,
120126
site_config: SiteConfig,
121127
password_manager: PasswordManager,
128+
url_builder: UrlBuilder,
122129
) -> Schema {
123130
let state = GraphQLState {
124131
pool: pool.clone(),
125132
policy_factory: Arc::clone(policy_factory),
126133
homeserver_connection: Arc::new(homeserver_connection),
127134
site_config,
128135
password_manager,
136+
url_builder,
129137
};
130138
let state: BoxState = Box::new(state);
131139

crates/handlers/src/graphql/model/upstream_oauth.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use anyhow::Context as _;
88
use async_graphql::{Context, Object, ID};
99
use chrono::{DateTime, Utc};
1010
use mas_storage::{upstream_oauth2::UpstreamOAuthProviderRepository, user::UserRepository};
11+
use url::Url;
1112

1213
use super::{NodeType, User};
1314
use crate::graphql::state::ContextExt;
@@ -45,6 +46,26 @@ impl UpstreamOAuth2Provider {
4546
pub async fn client_id(&self) -> &str {
4647
&self.provider.client_id
4748
}
49+
50+
/// A human-readable name for this provider.
51+
pub async fn human_name(&self) -> Option<&str> {
52+
self.provider.human_name.as_deref()
53+
}
54+
55+
/// A brand identifier for this provider.
56+
///
57+
/// One of `google`, `github`, `gitlab`, `apple` or `facebook`.
58+
pub async fn brand_name(&self) -> Option<&str> {
59+
self.provider.brand_name.as_deref()
60+
}
61+
62+
/// URL to start the linking process of the current user with this provider.
63+
pub async fn link_url(&self, context: &Context<'_>) -> Url {
64+
let state = context.state();
65+
let url_builder = state.url_builder();
66+
let route = mas_router::UpstreamOAuth2Authorize::new(self.provider.id);
67+
url_builder.absolute_url_for(&route)
68+
}
4869
}
4970

5071
impl UpstreamOAuth2Link {
@@ -82,6 +103,11 @@ impl UpstreamOAuth2Link {
82103
&self.link.subject
83104
}
84105

106+
/// A human-readable name for the link subject.
107+
pub async fn human_account_name(&self) -> Option<&str> {
108+
self.link.human_account_name.as_deref()
109+
}
110+
85111
/// The provider for which this link is.
86112
pub async fn provider(
87113
&self,

crates/handlers/src/graphql/state.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use mas_data_model::SiteConfig;
88
use mas_matrix::HomeserverConnection;
99
use mas_policy::Policy;
10+
use mas_router::UrlBuilder;
1011
use mas_storage::{BoxClock, BoxRepository, BoxRng, RepositoryError};
1112

1213
use crate::{graphql::Requester, passwords::PasswordManager};
@@ -20,6 +21,7 @@ pub trait State {
2021
fn clock(&self) -> BoxClock;
2122
fn rng(&self) -> BoxRng;
2223
fn site_config(&self) -> &SiteConfig;
24+
fn url_builder(&self) -> &UrlBuilder;
2325
}
2426

2527
pub type BoxState = Box<dyn State + Send + Sync + 'static>;

crates/handlers/src/test_utils.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ impl TestState {
212212
rng: Arc::clone(&rng),
213213
clock: Arc::clone(&clock),
214214
password_manager: password_manager.clone(),
215+
url_builder: url_builder.clone(),
215216
};
216217
let state: crate::graphql::BoxState = Box::new(graphql_state);
217218

@@ -377,6 +378,7 @@ struct TestGraphQLState {
377378
clock: Arc<MockClock>,
378379
rng: Arc<Mutex<ChaChaRng>>,
379380
password_manager: PasswordManager,
381+
url_builder: UrlBuilder,
380382
}
381383

382384
#[async_trait]
@@ -401,6 +403,10 @@ impl graphql::State for TestGraphQLState {
401403
&self.homeserver_connection
402404
}
403405

406+
fn url_builder(&self) -> &UrlBuilder {
407+
&self.url_builder
408+
}
409+
404410
fn clock(&self) -> BoxClock {
405411
Box::new(self.clock.clone())
406412
}

frontend/schema.graphql

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1535,6 +1535,10 @@ type UpstreamOAuth2Link implements Node & CreationEvent {
15351535
"""
15361536
subject: String!
15371537
"""
1538+
A human-readable name for the link subject.
1539+
"""
1540+
humanAccountName: String
1541+
"""
15381542
The provider for which this link is.
15391543
"""
15401544
provider: UpstreamOAuth2Provider!
@@ -1594,6 +1598,20 @@ type UpstreamOAuth2Provider implements Node & CreationEvent {
15941598
Client ID used for this provider.
15951599
"""
15961600
clientId: String!
1601+
"""
1602+
A human-readable name for this provider.
1603+
"""
1604+
humanName: String
1605+
"""
1606+
A brand identifier for this provider.
1607+
1608+
One of `google`, `github`, `gitlab`, `apple` or `facebook`.
1609+
"""
1610+
brandName: String
1611+
"""
1612+
URL to start the linking process of the current user with this provider.
1613+
"""
1614+
linkUrl: Url!
15971615
}
15981616

15991617
type UpstreamOAuth2ProviderConnection {

frontend/src/gql/graphql.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,6 +1116,8 @@ export type UpstreamOAuth2Link = CreationEvent & Node & {
11161116
__typename?: 'UpstreamOAuth2Link';
11171117
/** When the object was created. */
11181118
createdAt: Scalars['DateTime']['output'];
1119+
/** A human-readable name for the link subject. */
1120+
humanAccountName?: Maybe<Scalars['String']['output']>;
11191121
/** ID of the object. */
11201122
id: Scalars['ID']['output'];
11211123
/** The provider for which this link is. */
@@ -1149,14 +1151,24 @@ export type UpstreamOAuth2LinkEdge = {
11491151

11501152
export type UpstreamOAuth2Provider = CreationEvent & Node & {
11511153
__typename?: 'UpstreamOAuth2Provider';
1154+
/**
1155+
* A brand identifier for this provider.
1156+
*
1157+
* One of `google`, `github`, `gitlab`, `apple` or `facebook`.
1158+
*/
1159+
brandName?: Maybe<Scalars['String']['output']>;
11521160
/** Client ID used for this provider. */
11531161
clientId: Scalars['String']['output'];
11541162
/** When the object was created. */
11551163
createdAt: Scalars['DateTime']['output'];
1164+
/** A human-readable name for this provider. */
1165+
humanName?: Maybe<Scalars['String']['output']>;
11561166
/** ID of the object. */
11571167
id: Scalars['ID']['output'];
11581168
/** OpenID Connect issuer URL. */
11591169
issuer?: Maybe<Scalars['String']['output']>;
1170+
/** URL to start the linking process of the current user with this provider. */
1171+
linkUrl: Scalars['Url']['output'];
11601172
};
11611173

11621174
export type UpstreamOAuth2ProviderConnection = {

0 commit comments

Comments
 (0)