* Remove last Option<Vec.. from API. Fixes #2820 * Add empty allowed_instances check. * Adding comment for allowed_instances.
This commit is contained in:
parent
1e26709cb4
commit
eb40aeb89b
4 changed files with 38 additions and 45 deletions
|
@ -250,8 +250,8 @@ pub struct LeaveAdmin {
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct FederatedInstances {
|
pub struct FederatedInstances {
|
||||||
pub linked: Vec<Instance>,
|
pub linked: Vec<Instance>,
|
||||||
pub allowed: Option<Vec<Instance>>,
|
pub allowed: Vec<Instance>,
|
||||||
pub blocked: Option<Vec<Instance>>,
|
pub blocked: Vec<Instance>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
|
|
@ -318,10 +318,6 @@ pub async fn build_federated_instances(
|
||||||
let allowed = Instance::allowlist(pool).await?;
|
let allowed = Instance::allowlist(pool).await?;
|
||||||
let blocked = Instance::blocklist(pool).await?;
|
let blocked = Instance::blocklist(pool).await?;
|
||||||
|
|
||||||
// These can return empty vectors, so convert them to options
|
|
||||||
let allowed = (!allowed.is_empty()).then_some(allowed);
|
|
||||||
let blocked = (!blocked.is_empty()).then_some(blocked);
|
|
||||||
|
|
||||||
Ok(Some(FederatedInstances {
|
Ok(Some(FederatedInstances {
|
||||||
linked,
|
linked,
|
||||||
allowed,
|
allowed,
|
||||||
|
|
|
@ -69,16 +69,22 @@ fn check_apub_id_valid(apub_id: &Url, local_site_data: &LocalSiteData) -> Result
|
||||||
return Err("Federation disabled");
|
return Err("Federation disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(blocked) = local_site_data.blocked_instances.as_ref() {
|
if local_site_data
|
||||||
if blocked.iter().any(|i| domain.eq(&i.domain)) {
|
.blocked_instances
|
||||||
return Err("Domain is blocked");
|
.iter()
|
||||||
}
|
.any(|i| domain.eq(&i.domain))
|
||||||
|
{
|
||||||
|
return Err("Domain is blocked");
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(allowed) = local_site_data.allowed_instances.as_ref() {
|
// Only check this if there are instances in the allowlist
|
||||||
if !allowed.iter().any(|i| domain.eq(&i.domain)) {
|
if !local_site_data.allowed_instances.is_empty()
|
||||||
return Err("Domain is not in allowlist");
|
&& !local_site_data
|
||||||
}
|
.allowed_instances
|
||||||
|
.iter()
|
||||||
|
.any(|i| domain.eq(&i.domain))
|
||||||
|
{
|
||||||
|
return Err("Domain is not in allowlist");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -87,8 +93,8 @@ fn check_apub_id_valid(apub_id: &Url, local_site_data: &LocalSiteData) -> Result
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct LocalSiteData {
|
pub(crate) struct LocalSiteData {
|
||||||
local_site: Option<LocalSite>,
|
local_site: Option<LocalSite>,
|
||||||
allowed_instances: Option<Vec<Instance>>,
|
allowed_instances: Vec<Instance>,
|
||||||
blocked_instances: Option<Vec<Instance>>,
|
blocked_instances: Vec<Instance>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn fetch_local_site_data(
|
pub(crate) async fn fetch_local_site_data(
|
||||||
|
@ -96,12 +102,8 @@ pub(crate) async fn fetch_local_site_data(
|
||||||
) -> Result<LocalSiteData, diesel::result::Error> {
|
) -> Result<LocalSiteData, diesel::result::Error> {
|
||||||
// LocalSite may be missing
|
// LocalSite may be missing
|
||||||
let local_site = LocalSite::read(pool).await.ok();
|
let local_site = LocalSite::read(pool).await.ok();
|
||||||
let allowed = Instance::allowlist(pool).await?;
|
let allowed_instances = Instance::allowlist(pool).await?;
|
||||||
let blocked = Instance::blocklist(pool).await?;
|
let blocked_instances = Instance::blocklist(pool).await?;
|
||||||
|
|
||||||
// These can return empty vectors, so convert them to options
|
|
||||||
let allowed_instances = (!allowed.is_empty()).then_some(allowed);
|
|
||||||
let blocked_instances = (!blocked.is_empty()).then_some(blocked);
|
|
||||||
|
|
||||||
Ok(LocalSiteData {
|
Ok(LocalSiteData {
|
||||||
local_site,
|
local_site,
|
||||||
|
@ -126,26 +128,25 @@ pub(crate) fn check_apub_id_valid_with_strictness(
|
||||||
}
|
}
|
||||||
check_apub_id_valid(apub_id, local_site_data).map_err(LemmyError::from_message)?;
|
check_apub_id_valid(apub_id, local_site_data).map_err(LemmyError::from_message)?;
|
||||||
|
|
||||||
if let Some(allowed) = local_site_data.allowed_instances.as_ref() {
|
// Only check allowlist if this is a community, and there are instances in the allowlist
|
||||||
// Only check allowlist if this is a community
|
if is_strict && !local_site_data.allowed_instances.is_empty() {
|
||||||
if is_strict {
|
// need to allow this explicitly because apub receive might contain objects from our local
|
||||||
// need to allow this explicitly because apub receive might contain objects from our local
|
// instance.
|
||||||
// instance.
|
let mut allowed_and_local = local_site_data
|
||||||
let mut allowed_and_local = allowed
|
.allowed_instances
|
||||||
.iter()
|
.iter()
|
||||||
.map(|i| i.domain.clone())
|
.map(|i| i.domain.clone())
|
||||||
.collect::<Vec<String>>();
|
.collect::<Vec<String>>();
|
||||||
let local_instance = settings
|
let local_instance = settings
|
||||||
.get_hostname_without_port()
|
.get_hostname_without_port()
|
||||||
.expect("local hostname is valid");
|
.expect("local hostname is valid");
|
||||||
allowed_and_local.push(local_instance);
|
allowed_and_local.push(local_instance);
|
||||||
|
|
||||||
let domain = apub_id.domain().expect("apud id has domain").to_string();
|
let domain = apub_id.domain().expect("apud id has domain").to_string();
|
||||||
if !allowed_and_local.contains(&domain) {
|
if !allowed_and_local.contains(&domain) {
|
||||||
return Err(LemmyError::from_message(
|
return Err(LemmyError::from_message(
|
||||||
"Federation forbidden by strict allowlist",
|
"Federation forbidden by strict allowlist",
|
||||||
));
|
));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -64,7 +64,6 @@ pub(crate) mod tests {
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{source::secret::Secret, utils::build_db_pool_for_tests};
|
use lemmy_db_schema::{source::secret::Secret, utils::build_db_pool_for_tests};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
error::LemmyError,
|
|
||||||
rate_limit::{RateLimitCell, RateLimitConfig},
|
rate_limit::{RateLimitCell, RateLimitConfig},
|
||||||
settings::SETTINGS,
|
settings::SETTINGS,
|
||||||
};
|
};
|
||||||
|
@ -89,9 +88,6 @@ pub(crate) mod tests {
|
||||||
|
|
||||||
// TODO: would be nice if we didnt have to use a full context for tests.
|
// TODO: would be nice if we didnt have to use a full context for tests.
|
||||||
pub(crate) async fn init_context() -> Data<LemmyContext> {
|
pub(crate) async fn init_context() -> Data<LemmyContext> {
|
||||||
async fn x() -> Result<String, LemmyError> {
|
|
||||||
Ok(String::new())
|
|
||||||
}
|
|
||||||
// call this to run migrations
|
// call this to run migrations
|
||||||
let pool = build_db_pool_for_tests().await;
|
let pool = build_db_pool_for_tests().await;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue