diff --git a/crates/cli/src/util.rs b/crates/cli/src/util.rs index 27c23eeb5..e8b037e45 100644 --- a/crates/cli/src/util.rs +++ b/crates/cli/src/util.rs @@ -207,6 +207,7 @@ pub fn site_config_from_config( && account_config.password_change_allowed, account_recovery_allowed: password_config.enabled() && account_config.password_recovery_enabled, + account_deactivation_allowed: account_config.account_deactivation_allowed, captcha, minimum_password_complexity: password_config.minimum_complexity(), session_expiration, diff --git a/crates/config/src/sections/account.rs b/crates/config/src/sections/account.rs index 7be79e357..d621dbf4d 100644 --- a/crates/config/src/sections/account.rs +++ b/crates/config/src/sections/account.rs @@ -61,6 +61,11 @@ pub struct AccountConfig { /// This has no effect if password login is disabled. #[serde(default = "default_false", skip_serializing_if = "is_default_false")] pub password_recovery_enabled: bool, + + /// Whether users are allowed to delete their own account. Defaults to + /// `false`. + #[serde(default = "default_false", skip_serializing_if = "is_default_false")] + pub account_deactivation_allowed: bool, } impl Default for AccountConfig { @@ -71,6 +76,7 @@ impl Default for AccountConfig { password_registration_enabled: default_false(), password_change_allowed: default_true(), password_recovery_enabled: default_false(), + account_deactivation_allowed: default_false(), } } } @@ -83,6 +89,7 @@ impl AccountConfig { && is_default_true(&self.displayname_change_allowed) && is_default_true(&self.password_change_allowed) && is_default_false(&self.password_recovery_enabled) + && is_default_false(&self.account_deactivation_allowed) } } diff --git a/crates/data-model/src/site_config.rs b/crates/data-model/src/site_config.rs index 0e09f8a31..4688c0f11 100644 --- a/crates/data-model/src/site_config.rs +++ b/crates/data-model/src/site_config.rs @@ -76,6 +76,9 @@ pub struct SiteConfig { /// Whether users can recover their account via email. pub account_recovery_allowed: bool, + /// Whether users can delete their own account. + pub account_deactivation_allowed: bool, + /// Captcha configuration pub captcha: Option, diff --git a/crates/handlers/src/graphql/model/site_config.rs b/crates/handlers/src/graphql/model/site_config.rs index dc2cae188..598c0aabc 100644 --- a/crates/handlers/src/graphql/model/site_config.rs +++ b/crates/handlers/src/graphql/model/site_config.rs @@ -46,6 +46,9 @@ pub struct SiteConfig { /// Whether passwords are enabled and users can register using a password. password_registration_enabled: bool, + /// Whether users can delete their own account. + account_deactivation_allowed: bool, + /// Minimum password complexity, from 0 to 4, in terms of a zxcvbn score. /// The exact scorer (including dictionaries and other data tables) /// in use is . @@ -93,6 +96,7 @@ impl SiteConfig { password_login_enabled: data_model.password_login_enabled, password_change_allowed: data_model.password_change_allowed, password_registration_enabled: data_model.password_registration_enabled, + account_deactivation_allowed: data_model.account_deactivation_allowed, minimum_password_complexity: data_model.minimum_password_complexity, } } diff --git a/crates/handlers/src/test_utils.rs b/crates/handlers/src/test_utils.rs index 60da629e2..1cb6f29cd 100644 --- a/crates/handlers/src/test_utils.rs +++ b/crates/handlers/src/test_utils.rs @@ -137,6 +137,7 @@ pub fn test_site_config() -> SiteConfig { displayname_change_allowed: true, password_change_allowed: true, account_recovery_allowed: true, + account_deactivation_allowed: true, captcha: None, minimum_password_complexity: 1, session_expiration: None, diff --git a/docs/config.schema.json b/docs/config.schema.json index a998f08fd..93bb96b91 100644 --- a/docs/config.schema.json +++ b/docs/config.schema.json @@ -2463,6 +2463,10 @@ "password_recovery_enabled": { "description": "Whether email-based password recovery is enabled. Defaults to `false`.\n\nThis has no effect if password login is disabled.", "type": "boolean" + }, + "account_deactivation_allowed": { + "description": "Whether users are allowed to delete their own account. Defaults to `false`.", + "type": "boolean" } } }, diff --git a/frontend/schema.graphql b/frontend/schema.graphql index eeb9b44e4..14775ba2d 100644 --- a/frontend/schema.graphql +++ b/frontend/schema.graphql @@ -1599,6 +1599,10 @@ type SiteConfig implements Node { """ passwordRegistrationEnabled: Boolean! """ + Whether users can delete their own account. + """ + accountDeactivationAllowed: Boolean! + """ Minimum password complexity, from 0 to 4, in terms of a zxcvbn score. The exact scorer (including dictionaries and other data tables) in use is . diff --git a/frontend/src/gql/graphql.ts b/frontend/src/gql/graphql.ts index 5910ff98e..c76a8d3c8 100644 --- a/frontend/src/gql/graphql.ts +++ b/frontend/src/gql/graphql.ts @@ -1161,6 +1161,8 @@ export type SetPrimaryEmailStatus = export type SiteConfig = Node & { __typename?: 'SiteConfig'; + /** Whether users can delete their own account. */ + accountDeactivationAllowed: Scalars['Boolean']['output']; /** The configuration of CAPTCHA provider. */ captchaConfig?: Maybe; /** Whether users can change their display name. */