Import upstream v0.16.22, stripped

Upstream commit: 474dd0229cb20cf513036619781ed97bd8073c3f
Enterprise-only files removed or emptied: 63
Enterprise-only snippets removed: 117 in 50 files
Dangling module declarations removed: 5
Cargo edits turning enterprise off: 14
Verification: clean
Enterprise feature gates left for rebuilt features: 19 in 18 files

Produced by tools/fork/strip.py. The full report is in docs/fork/strip-reports/ on main.
This commit is contained in:
jcoffey-dev committed 2026-09-18 10:21:56 -07:00
commit 7dae9b29fd
1650 files changed
+485521

No files matched your search

+209
View File
@@ -0,0 +1,209 @@
/*
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
*/
use crate::registry::mapping::{
ObjectResponse, RegistrySetResponse, ValidationResult, principal::validate_tenant_quota,
};
use common::network::{dkim::generate_dkim_selector, dns::update::DnsUpdater};
use jmap_proto::error::set::{SetError, SetErrorType};
use registry::{
schema::{
enums::{AcmeChallengeType, DkimSignatureType, DnsRecordType, TenantStorageQuota},
prelude::{ObjectType, Property},
structs::{
AcmeProvider, CertificateManagement, DkimManagement, DkimManagementProperties,
DnsManagement, DnsServer, Domain, Task, TaskDnsManagement, TaskDomainManagement,
TaskStatus,
},
},
types::map::Map,
};
use types::id::Id;
pub(crate) async fn validate_domain(
set: &RegistrySetResponse<'_>,
domain: &mut Domain,
old_domain: Option<&Domain>,
tasks: &mut Vec<Task>,
) -> ValidationResult {
let response = if old_domain.is_none() {
match validate_tenant_quota(set.server, set.access_token, TenantStorageQuota::MaxDomains)
.await?
{
Ok(response) => response,
Err(err) => {
return Ok(Err(err));
}
}
} else {
ObjectResponse::default()
};
// Validate DKIM selector template
if let DkimManagement::Automatic(DkimManagementProperties {
selector_template, ..
}) = &domain.dkim_management
&& old_domain.is_none_or(|old| {
matches!(
&old.dkim_management,
DkimManagement::Automatic(DkimManagementProperties {
selector_template: old_selector_template,
..
}) if old_selector_template != selector_template
)
})
&& let Err(err) =
generate_dkim_selector(selector_template, DkimSignatureType::Dkim1RsaSha256)
{
return Ok(Err(SetError::invalid_properties()
.with_property(Property::SelectorTemplate)
.with_description(err)));
}
// Validate that names and aliases do not collide with another domain
let registry = set.server.registry();
if old_domain.is_none_or(|old| old.name != domain.name)
&& let Some(existing) = registry
.primary_key(
ObjectType::Domain.into(),
Property::Aliases,
domain.name.as_bytes().to_vec(),
)
.await?
{
return Ok(Err(SetError::new(SetErrorType::PrimaryKeyViolation)
.with_property(Property::Name)
.with_object_id(existing)));
}
for alias in domain.aliases.iter() {
if alias == &domain.name
|| old_domain.is_some_and(|old| old.aliases.contains(alias) || &old.name == alias)
{
continue;
}
for index in [Property::Name, Property::Aliases] {
if let Some(existing) = registry
.primary_key(ObjectType::Domain.into(), index, alias.as_bytes().to_vec())
.await?
{
return Ok(Err(SetError::new(SetErrorType::PrimaryKeyViolation)
.with_property(Property::Aliases)
.with_object_id(existing)));
}
}
}
// Schedule DNS update task
let will_trigger_dkim = matches!(domain.dkim_management, DkimManagement::Automatic(_))
&& old_domain
.is_none_or(|old| !matches!(old.dkim_management, DkimManagement::Automatic(_)));
let will_trigger_acme = if let DnsManagement::Automatic(details) = &domain.dns_management
&& old_domain.is_none_or(|old| !matches!(old.dns_management, DnsManagement::Automatic(_)))
{
let on_success_renew_certificate = old_domain.is_none()
&& matches!(
domain.certificate_management,
CertificateManagement::Automatic(_)
);
tasks.push(Task::DnsManagement(TaskDnsManagement {
domain_id: Id::default(),
update_records: Map::new(
details
.publish_records
.iter()
.filter(|&&r| r != DnsRecordType::Dkim || !will_trigger_dkim)
.copied()
.collect(),
),
on_success_renew_certificate,
status: TaskStatus::now(),
}));
on_success_renew_certificate
} else {
false
};
// Schedule DKIM key rotation task
if will_trigger_dkim {
tasks.push(Task::DkimManagement(TaskDomainManagement {
domain_id: Id::default(),
status: TaskStatus::now(),
}));
}
// Schedule ACME renewal task if needed
if !will_trigger_acme
&& let CertificateManagement::Automatic(details) = &domain.certificate_management
&& old_domain.is_none_or(|old| {
!matches!(
old.certificate_management,
CertificateManagement::Automatic(_)
)
})
{
let Some(provider) = set
.server
.registry()
.object::<AcmeProvider>(details.acme_provider_id)
.await?
else {
return Ok(Err(SetError::invalid_properties()
.with_property(Property::AcmeProviderId)
.with_description("ACME provider not found")));
};
if matches!(provider.challenge_type, AcmeChallengeType::Dns01)
&& !matches!(domain.dns_management, DnsManagement::Automatic(_))
{
return Ok(Err(SetError::invalid_properties()
.with_property(Property::AcmeProviderId)
.with_description(
"ACME provider requires automatic DNS management",
)));
}
tasks.push(Task::AcmeRenewal(TaskDomainManagement {
domain_id: Id::default(),
status: TaskStatus::now(),
}));
}
Ok(Ok(response))
}
pub(crate) async fn validate_dns_server(
set: &RegistrySetResponse<'_>,
dns: &mut DnsServer,
old_dns: Option<&DnsServer>,
) -> ValidationResult {
let response = if old_dns.is_none() {
match validate_tenant_quota(
set.server,
set.access_token,
TenantStorageQuota::MaxDnsServers,
)
.await?
{
Ok(response) => response,
Err(err) => {
return Ok(Err(err));
}
}
} else {
ObjectResponse::default()
};
if old_dns.is_none_or(|old_dns| old_dns != dns)
&& let Err(err) = DnsUpdater::build(dns.clone(), set.server.core.clone()).await
{
return Ok(Err(SetError::invalid_properties()
.with_description(format!("Failed to build DNS server: {err}"))));
}
Ok(Ok(response))
}