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:
commit
7dae9b29fd
1650 files changed
+485521
No files matched your search
@@ -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))
|
||||
}
|
||||
Reference in new issue
Block a user