Skip to content

Commit 3e3d823

Browse files
committed
GraphQL API changes
1 parent d663223 commit 3e3d823

File tree

21 files changed

+1246
-13
lines changed

21 files changed

+1246
-13
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/cli/src/app_state.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use mas_context::LogContext;
1212
use mas_data_model::SiteConfig;
1313
use mas_handlers::{
1414
ActivityTracker, BoundActivityTracker, CookieManager, ErrorWrapper, GraphQLSchema, Limiter,
15-
MetadataCache, RequesterFingerprint, passwords::PasswordManager,
15+
MetadataCache, RequesterFingerprint, passwords::PasswordManager, webauthn::Webauthn,
1616
};
1717
use mas_i18n::Translator;
1818
use mas_keystore::{Encrypter, Keystore};
@@ -49,6 +49,7 @@ pub struct AppState {
4949
pub activity_tracker: ActivityTracker,
5050
pub trusted_proxies: Vec<IpNetwork>,
5151
pub limiter: Limiter,
52+
pub webauthn: Webauthn,
5253
}
5354

5455
impl AppState {
@@ -216,6 +217,12 @@ impl FromRef<AppState> for Arc<dyn HomeserverConnection> {
216217
}
217218
}
218219

220+
impl FromRef<AppState> for Webauthn {
221+
fn from_ref(input: &AppState) -> Self {
222+
input.webauthn.clone()
223+
}
224+
}
225+
219226
impl FromRequestParts<AppState> for BoxClock {
220227
type Rejection = Infallible;
221228

crates/cli/src/commands/server.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use crate::{
2929
database_pool_from_config, homeserver_connection_from_config,
3030
load_policy_factory_dynamic_data_continuously, mailer_from_config,
3131
password_manager_from_config, policy_factory_from_config, site_config_from_config,
32-
templates_from_config, test_mailer_in_background,
32+
templates_from_config, test_mailer_in_background, webauthn_from_config,
3333
},
3434
};
3535

@@ -187,6 +187,8 @@ impl Options {
187187

188188
let password_manager = password_manager_from_config(&config.passwords).await?;
189189

190+
let webauthn = webauthn_from_config(&config.http, &config.experimental)?;
191+
190192
// The upstream OIDC metadata cache
191193
let metadata_cache = MetadataCache::new();
192194

@@ -222,6 +224,7 @@ impl Options {
222224
password_manager.clone(),
223225
url_builder.clone(),
224226
limiter.clone(),
227+
webauthn.clone(),
225228
);
226229

227230
let state = {
@@ -242,6 +245,7 @@ impl Options {
242245
activity_tracker,
243246
trusted_proxies,
244247
limiter,
248+
webauthn,
245249
};
246250
s.init_metrics();
247251
s.init_metadata_cache();

crates/cli/src/util.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ use std::{sync::Arc, time::Duration};
99
use anyhow::Context;
1010
use mas_config::{
1111
AccountConfig, BrandingConfig, CaptchaConfig, DatabaseConfig, EmailConfig, EmailSmtpMode,
12-
EmailTransportKind, ExperimentalConfig, HomeserverKind, MatrixConfig, PasswordsConfig,
13-
PolicyConfig, TemplatesConfig,
12+
EmailTransportKind, ExperimentalConfig, HomeserverKind, HttpConfig, MatrixConfig,
13+
PasswordsConfig, PolicyConfig, TemplatesConfig,
1414
};
1515
use mas_context::LogContext;
1616
use mas_data_model::{SessionExpirationConfig, SiteConfig};
1717
use mas_email::{MailTransport, Mailer};
18-
use mas_handlers::passwords::PasswordManager;
18+
use mas_handlers::{passwords::PasswordManager, webauthn::Webauthn};
1919
use mas_matrix::{HomeserverConnection, ReadOnlyHomeserverConnection};
2020
use mas_matrix_synapse::SynapseConnection;
2121
use mas_policy::PolicyFactory;
@@ -490,6 +490,16 @@ pub fn homeserver_connection_from_config(
490490
}
491491
}
492492

493+
pub fn webauthn_from_config(
494+
http_config: &HttpConfig,
495+
experimental_config: &ExperimentalConfig,
496+
) -> Result<Webauthn, anyhow::Error> {
497+
Webauthn::new(
498+
&http_config.public_base,
499+
experimental_config.passkeys.as_ref(),
500+
)
501+
}
502+
493503
#[cfg(test)]
494504
mod tests {
495505
use rand::SeedableRng;

crates/config/src/sections/experimental.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ pub struct PasskeysConfig {
5252
/// Whether passkeys are enabled or not
5353
#[serde(default)]
5454
pub enabled: bool,
55+
/// Relying Party Identifier to use
56+
///
57+
/// If not set, the host from `public_base` is used
58+
#[serde(default)]
59+
pub rpid: Option<String>,
60+
/// Additional allowed origins. `rpid` and `public_base` are already allowed
61+
#[serde(default)]
62+
pub allowed_origins: Option<Vec<String>>,
5563
}
5664

5765
/// Configuration sections for experimental options

crates/config/src/sections/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub use self::{
3232
clients::{ClientAuthMethodConfig, ClientConfig, ClientsConfig},
3333
database::{DatabaseConfig, PgSslMode},
3434
email::{EmailConfig, EmailSmtpMode, EmailTransportKind},
35-
experimental::ExperimentalConfig,
35+
experimental::{ExperimentalConfig, PasskeysConfig},
3636
http::{
3737
BindConfig as HttpBindConfig, HttpConfig, ListenerConfig as HttpListenerConfig,
3838
Resource as HttpResource, TlsConfig as HttpTlsConfig, UnixOrTcp,

crates/handlers/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ rand.workspace = true
8888
rand_chacha.workspace = true
8989
headers.workspace = true
9090
ulid.workspace = true
91+
webauthn_rp.workspace = true
9192

9293
mas-axum-utils.workspace = true
9394
mas-config.workspace = true

crates/handlers/src/graphql/mod.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ use self::{
5555
};
5656
use crate::{
5757
BoundActivityTracker, Limiter, RequesterFingerprint, impl_from_error_for_route,
58-
passwords::PasswordManager,
58+
passwords::PasswordManager, webauthn::Webauthn,
5959
};
6060

6161
#[cfg(test)]
@@ -76,6 +76,7 @@ struct GraphQLState {
7676
password_manager: PasswordManager,
7777
url_builder: UrlBuilder,
7878
limiter: Limiter,
79+
webauthn: Webauthn,
7980
}
8081

8182
#[async_trait::async_trait]
@@ -108,6 +109,10 @@ impl state::State for GraphQLState {
108109
&self.limiter
109110
}
110111

112+
fn webauthn(&self) -> &Webauthn {
113+
&self.webauthn
114+
}
115+
111116
fn clock(&self) -> BoxClock {
112117
let clock = SystemClock::default();
113118
Box::new(clock)
@@ -131,6 +136,7 @@ pub fn schema(
131136
password_manager: PasswordManager,
132137
url_builder: UrlBuilder,
133138
limiter: Limiter,
139+
webauthn: Webauthn,
134140
) -> Schema {
135141
let state = GraphQLState {
136142
repository_factory,
@@ -140,6 +146,7 @@ pub fn schema(
140146
password_manager,
141147
url_builder,
142148
limiter,
149+
webauthn,
143150
};
144151
let state: BoxState = Box::new(state);
145152

@@ -519,6 +526,12 @@ impl OwnerId for mas_data_model::UpstreamOAuthLink {
519526
}
520527
}
521528

529+
impl OwnerId for mas_data_model::UserPasskey {
530+
fn owner_id(&self) -> Option<Ulid> {
531+
Some(self.user_id)
532+
}
533+
}
534+
522535
/// A dumb wrapper around a `Ulid` to implement `OwnerId` for it.
523536
pub struct UserId(Ulid);
524537

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ pub use self::{
2626
oauth::{OAuth2Client, OAuth2Session},
2727
site_config::{SITE_CONFIG_ID, SiteConfig},
2828
upstream_oauth::{UpstreamOAuth2Link, UpstreamOAuth2Provider},
29-
users::{AppSession, User, UserEmail, UserEmailAuthentication, UserRecoveryTicket},
29+
users::{
30+
AppSession, User, UserEmail, UserEmailAuthentication, UserPasskey, UserRecoveryTicket,
31+
},
3032
viewer::{Anonymous, Viewer, ViewerSession},
3133
};
3234

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ pub enum NodeType {
2929
UserEmail,
3030
UserEmailAuthentication,
3131
UserRecoveryTicket,
32+
UserPasskey,
33+
UserPasskeyChallenge,
3234
}
3335

3436
#[derive(Debug, Error)]
@@ -55,6 +57,8 @@ impl NodeType {
5557
NodeType::UserEmail => "user_email",
5658
NodeType::UserEmailAuthentication => "user_email_authentication",
5759
NodeType::UserRecoveryTicket => "user_recovery_ticket",
60+
NodeType::UserPasskey => "user_passkey",
61+
NodeType::UserPasskeyChallenge => "user_passkey_challenge",
5862
}
5963
}
6064

@@ -72,6 +76,8 @@ impl NodeType {
7276
"user_email" => Some(NodeType::UserEmail),
7377
"user_email_authentication" => Some(NodeType::UserEmailAuthentication),
7478
"user_recovery_ticket" => Some(NodeType::UserRecoveryTicket),
79+
"user_passkey" => Some(NodeType::UserPasskey),
80+
"user_passkey_challenge" => Some(NodeType::UserPasskeyChallenge),
7581
_ => None,
7682
}
7783
}

0 commit comments

Comments
 (0)