mirror of
https://forgejo.ellis.link/continuwuation/continuwuity/
synced 2026-07-09 10:41:43 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 19204b097d | |||
| 567d809efe | |||
| 8171e3d614 |
@@ -0,0 +1 @@
|
||||
Users will now be prevented from removing their email if the server is configured to require an email when registering an account.
|
||||
@@ -0,0 +1 @@
|
||||
Fixed a situation where multiple email addresses could be associated with one user when that user changes their email address.
|
||||
@@ -2104,6 +2104,9 @@
|
||||
# Whether to require that users provide an email address when they
|
||||
# register.
|
||||
#
|
||||
# If either this option or `require_email_for_token_registration` are set,
|
||||
# users will not be allowed to remove their email address.
|
||||
#
|
||||
#require_email_for_registration = false
|
||||
|
||||
# Whether to require that users who register with a registration token
|
||||
|
||||
@@ -53,6 +53,10 @@ pub(crate) async fn request_3pid_management_token_via_email_route(
|
||||
State(services): State<crate::State>,
|
||||
body: Ruma<request_3pid_management_token_via_email::v3::Request>,
|
||||
) -> Result<request_3pid_management_token_via_email::v3::Response> {
|
||||
if !services.threepid.email_requirement().may_change() {
|
||||
return Err!(Request(Forbidden("You may not change your email address.")));
|
||||
}
|
||||
|
||||
let Ok(email) = Address::try_from(body.email.clone()) else {
|
||||
return Err!(Request(InvalidParam("Invalid email address.")));
|
||||
};
|
||||
@@ -105,6 +109,10 @@ pub(crate) async fn add_3pid_route(
|
||||
) -> Result<add_3pid::v3::Response> {
|
||||
let sender_user = body.sender_user();
|
||||
|
||||
if !services.threepid.email_requirement().may_change() {
|
||||
return Err!(Request(Forbidden("You may not change your email address.")));
|
||||
}
|
||||
|
||||
// Require password auth to add an email
|
||||
let _ = services
|
||||
.uiaa
|
||||
@@ -138,6 +146,10 @@ pub(crate) async fn delete_3pid_route(
|
||||
});
|
||||
}
|
||||
|
||||
if !services.threepid.email_requirement().may_remove() {
|
||||
return Err!(Request(Forbidden("You may not remove your email address.")));
|
||||
}
|
||||
|
||||
if services
|
||||
.threepid
|
||||
.disassociate_localpart_email(sender_user.localpart())
|
||||
|
||||
@@ -32,7 +32,7 @@ pub(crate) async fn get_capabilities_route(
|
||||
|
||||
// Only allow 3pid changes if SMTP is configured
|
||||
capabilities.thirdparty_id_changes = ThirdPartyIdChangesCapability {
|
||||
enabled: services.mailer.mailer().is_some(),
|
||||
enabled: services.threepid.email_requirement().may_change(),
|
||||
};
|
||||
|
||||
capabilities.get_login_token = GetLoginTokenCapability {
|
||||
|
||||
@@ -2516,6 +2516,9 @@ pub struct SmtpConfig {
|
||||
/// Whether to require that users provide an email address when they
|
||||
/// register.
|
||||
///
|
||||
/// If either this option or `require_email_for_token_registration` are set,
|
||||
/// users will not be allowed to remove their email address.
|
||||
///
|
||||
/// default: false
|
||||
#[serde(default)]
|
||||
pub require_email_for_registration: bool,
|
||||
|
||||
@@ -25,6 +25,23 @@ pub struct Service {
|
||||
ratelimiter: DefaultKeyedRateLimiter<Address>,
|
||||
}
|
||||
|
||||
pub enum EmailRequirement {
|
||||
/// Users may change their email, but cannot remove it entirely.
|
||||
Required,
|
||||
/// Users may change or remove their email.
|
||||
Optional,
|
||||
/// Users may not change their email at all.
|
||||
Unavailable,
|
||||
}
|
||||
|
||||
impl EmailRequirement {
|
||||
#[must_use]
|
||||
pub fn may_change(&self) -> bool { matches!(self, Self::Required | Self::Optional) }
|
||||
|
||||
#[must_use]
|
||||
pub fn may_remove(&self) -> bool { matches!(self, Self::Optional) }
|
||||
}
|
||||
|
||||
struct Data {
|
||||
localpart_email: Arc<Map>,
|
||||
email_localpart: Arc<Map>,
|
||||
@@ -64,6 +81,19 @@ impl Service {
|
||||
Quota::per_minute(nonzero!(10_u32)).allow_burst(nonzero!(2_u32));
|
||||
const VALIDATION_URL_PATH: &str = "/_continuwuity/3pid/email/validate";
|
||||
|
||||
/// Check if users are required to have an email address.
|
||||
pub fn email_requirement(&self) -> EmailRequirement {
|
||||
if let Some(smtp) = &self.services.config.smtp {
|
||||
if smtp.require_email_for_registration || smtp.require_email_for_token_registration {
|
||||
EmailRequirement::Required
|
||||
} else {
|
||||
EmailRequirement::Optional
|
||||
}
|
||||
} else {
|
||||
EmailRequirement::Unavailable
|
||||
}
|
||||
}
|
||||
|
||||
/// Send a validation message to an email address.
|
||||
///
|
||||
/// Returns the validation session ID on success.
|
||||
@@ -234,6 +264,9 @@ pub async fn associate_localpart_email(
|
||||
| None => {
|
||||
// The supplied email is not already in use.
|
||||
|
||||
// Remove the user's existing email first.
|
||||
let _ = self.disassociate_localpart_email(localpart).await;
|
||||
|
||||
let email: &str = email.as_ref();
|
||||
self.db.localpart_email.insert(localpart, email);
|
||||
self.db.email_localpart.insert(email, localpart);
|
||||
|
||||
Reference in New Issue
Block a user