1// Copyright 2024 New Vector Ltd.
2// Copyright 2024 The Matrix.org Foundation C.I.C.
3//
4// SPDX-License-Identifier: AGPL-3.0-only
5// Please see LICENSE in the repository root for full details.
67#![allow(clippy::str_to_string)] // ComplexObject macro uses &str.to_string()
89use async_graphql::{ComplexObject, Enum, ID, SimpleObject};
10use url::Url;
1112pub const SITE_CONFIG_ID: &str = "site_config";
13pub const CAPTCHA_CONFIG_ID: &str = "captcha_config";
1415#[derive(SimpleObject)]
16#[graphql(complex)]
17#[allow(clippy::struct_excessive_bools)]
18pub struct SiteConfig {
19/// The configuration of CAPTCHA provider.
20captcha_config: Option<CaptchaConfig>,
2122/// The server name of the homeserver.
23server_name: String,
2425/// The URL to the privacy policy.
26policy_uri: Option<Url>,
2728/// The URL to the terms of service.
29tos_uri: Option<Url>,
3031/// Imprint to show in the footer.
32imprint: Option<String>,
3334/// Whether users can change their email.
35email_change_allowed: bool,
3637/// Whether users can change their display name.
38display_name_change_allowed: bool,
3940/// Whether passwords are enabled for login.
41password_login_enabled: bool,
4243/// Whether passwords are enabled and users can change their own passwords.
44password_change_allowed: bool,
4546/// Whether passwords are enabled and users can register using a password.
47password_registration_enabled: bool,
4849/// Whether users can delete their own account.
50account_deactivation_allowed: bool,
5152/// Minimum password complexity, from 0 to 4, in terms of a zxcvbn score.
53 /// The exact scorer (including dictionaries and other data tables)
54 /// in use is <https://crates.io/crates/zxcvbn>.
55minimum_password_complexity: u8,
5657/// Whether users can log in with their email address.
58login_with_email_allowed: bool,
59}
6061#[derive(SimpleObject)]
62#[graphql(complex)]
63pub struct CaptchaConfig {
64/// Which Captcha service is being used
65pub service: CaptchaService,
6667/// The site key used by the instance
68pub site_key: String,
69}
7071/// Which Captcha service is being used
72#[derive(Enum, Debug, Clone, Copy, PartialEq, Eq)]
73pub enum CaptchaService {
74 RecaptchaV2,
75 CloudflareTurnstile,
76 HCaptcha,
77}
7879#[ComplexObject]
80impl SiteConfig {
81/// The ID of the site configuration.
82pub async fn id(&self) -> ID {
83 SITE_CONFIG_ID.into()
84 }
85}
8687impl SiteConfig {
88/// Create a new [`SiteConfig`] from the data model
89 /// [`mas_data_model:::SiteConfig`].
90pub fn new(data_model: &mas_data_model::SiteConfig) -> Self {
91Self {
92 captcha_config: data_model.captcha.as_ref().map(CaptchaConfig::new),
93 server_name: data_model.server_name.clone(),
94 policy_uri: data_model.policy_uri.clone(),
95 tos_uri: data_model.tos_uri.clone(),
96 imprint: data_model.imprint.clone(),
97 email_change_allowed: data_model.email_change_allowed,
98 display_name_change_allowed: data_model.displayname_change_allowed,
99 password_login_enabled: data_model.password_login_enabled,
100 password_change_allowed: data_model.password_change_allowed,
101 password_registration_enabled: data_model.password_registration_enabled,
102 account_deactivation_allowed: data_model.account_deactivation_allowed,
103 minimum_password_complexity: data_model.minimum_password_complexity,
104 login_with_email_allowed: data_model.login_with_email_allowed,
105 }
106 }
107}
108109#[ComplexObject]
110impl CaptchaConfig {
111pub async fn id(&self) -> ID {
112 CAPTCHA_CONFIG_ID.into()
113 }
114}
115116impl CaptchaConfig {
117/// Create a new [`CaptchaConfig`] from the data model
118 /// [`mas_data_model:::CaptchaConfig`].
119pub fn new(data_model: &mas_data_model::CaptchaConfig) -> Self {
120Self {
121 service: match data_model.service {
122 mas_data_model::CaptchaService::RecaptchaV2 => CaptchaService::RecaptchaV2,
123 mas_data_model::CaptchaService::CloudflareTurnstile => {
124 CaptchaService::CloudflareTurnstile
125 }
126 mas_data_model::CaptchaService::HCaptcha => CaptchaService::HCaptcha,
127 },
128 site_key: data_model.site_key.clone(),
129 }
130 }
131}