Rewrite federation settings
This commit is contained in:
parent
c95165b01a
commit
af189c59f3
10 changed files with 52 additions and 26 deletions
10
docker/federation-test/docker-compose.yml
vendored
10
docker/federation-test/docker-compose.yml
vendored
|
@ -10,8 +10,9 @@ services:
|
||||||
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_alpha:5432/lemmy
|
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_alpha:5432/lemmy
|
||||||
- LEMMY_JWT_SECRET=changeme
|
- LEMMY_JWT_SECRET=changeme
|
||||||
- LEMMY_FRONT_END_DIR=/app/dist
|
- LEMMY_FRONT_END_DIR=/app/dist
|
||||||
- LEMMY_FEDERATION_ENABLED=true
|
- LEMMY_FEDERATION__ENABLED=true
|
||||||
- LEMMY_FEDERATED_INSTANCE=lemmy_beta:8541
|
- LEMMY_FEDERATION__FOLLOWED_INSTANCES=lemmy_beta:8541
|
||||||
|
- LEMMY_FEDERATION__TLS_ENABLED=false
|
||||||
- LEMMY_PORT=8540
|
- LEMMY_PORT=8540
|
||||||
- RUST_BACKTRACE=1
|
- RUST_BACKTRACE=1
|
||||||
restart: always
|
restart: always
|
||||||
|
@ -36,8 +37,9 @@ services:
|
||||||
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_beta:5432/lemmy
|
- LEMMY_DATABASE_URL=postgres://lemmy:password@postgres_beta:5432/lemmy
|
||||||
- LEMMY_JWT_SECRET=changeme
|
- LEMMY_JWT_SECRET=changeme
|
||||||
- LEMMY_FRONT_END_DIR=/app/dist
|
- LEMMY_FRONT_END_DIR=/app/dist
|
||||||
- LEMMY_FEDERATION_ENABLED=true
|
- LEMMY_FEDERATION__ENABLED=true
|
||||||
- LEMMY_FEDERATED_INSTANCE=lemmy_alpha:8540
|
- LEMMY_FEDERATION__FOLLOWED_INSTANCES=lemmy_alpha:8540
|
||||||
|
- LEMMY_FEDERATION__TLS_ENABLED=false
|
||||||
- LEMMY_PORT=8541
|
- LEMMY_PORT=8541
|
||||||
- RUST_BACKTRACE=1
|
- RUST_BACKTRACE=1
|
||||||
restart: always
|
restart: always
|
||||||
|
|
14
server/config/defaults.hjson
vendored
14
server/config/defaults.hjson
vendored
|
@ -24,11 +24,6 @@
|
||||||
jwt_secret: "changeme"
|
jwt_secret: "changeme"
|
||||||
# The dir for the front end
|
# The dir for the front end
|
||||||
front_end_dir: "../ui/dist"
|
front_end_dir: "../ui/dist"
|
||||||
# whether to enable activitypub federation. this feature is in alpha, do not enable in production.
|
|
||||||
federation_enabled: false
|
|
||||||
// another instance to federate with. this should be a list, but it seems like lists cant be set from environment
|
|
||||||
// https://github.com/mehcode/config-rs/issues/117
|
|
||||||
federated_instance: null
|
|
||||||
# rate limits for various user actions, by user ip
|
# rate limits for various user actions, by user ip
|
||||||
rate_limit: {
|
rate_limit: {
|
||||||
# maximum number of messages created in interval
|
# maximum number of messages created in interval
|
||||||
|
@ -44,6 +39,15 @@
|
||||||
# interval length for registration limit
|
# interval length for registration limit
|
||||||
register_per_second: 3600
|
register_per_second: 3600
|
||||||
}
|
}
|
||||||
|
# settings related to activitypub federation
|
||||||
|
federation: {
|
||||||
|
# whether to enable activitypub federation. this feature is in alpha, do not enable in production.
|
||||||
|
enabled: false
|
||||||
|
# comma seperated list of instances to follow
|
||||||
|
followed_instances: ""
|
||||||
|
# whether tls is required for activitypub. only disable this for debugging, never for producion.
|
||||||
|
tls_enabled: true
|
||||||
|
}
|
||||||
# # email sending configuration
|
# # email sending configuration
|
||||||
# email: {
|
# email: {
|
||||||
# # hostname of the smtp server
|
# # hostname of the smtp server
|
||||||
|
|
|
@ -121,7 +121,7 @@ impl Perform<GetCommunityResponse> for Oper<GetCommunity> {
|
||||||
let data: &GetCommunity = &self.data;
|
let data: &GetCommunity = &self.data;
|
||||||
|
|
||||||
if data.name.is_some()
|
if data.name.is_some()
|
||||||
&& Settings::get().federation_enabled
|
&& Settings::get().federation.enabled
|
||||||
&& data.name.as_ref().unwrap().contains('@')
|
&& data.name.as_ref().unwrap().contains('@')
|
||||||
{
|
{
|
||||||
return get_remote_community(data.name.as_ref().unwrap());
|
return get_remote_community(data.name.as_ref().unwrap());
|
||||||
|
@ -344,7 +344,7 @@ impl Perform<ListCommunitiesResponse> for Oper<ListCommunities> {
|
||||||
let data: &ListCommunities = &self.data;
|
let data: &ListCommunities = &self.data;
|
||||||
|
|
||||||
let local_only = data.local_only.unwrap_or(false);
|
let local_only = data.local_only.unwrap_or(false);
|
||||||
if Settings::get().federation_enabled && !local_only {
|
if Settings::get().federation.enabled && !local_only {
|
||||||
return Ok(ListCommunitiesResponse {
|
return Ok(ListCommunitiesResponse {
|
||||||
communities: get_all_communities()?,
|
communities: get_all_communities()?,
|
||||||
});
|
});
|
||||||
|
|
|
@ -221,7 +221,7 @@ impl Perform<GetPostsResponse> for Oper<GetPosts> {
|
||||||
fn perform(&self, conn: &PgConnection) -> Result<GetPostsResponse, Error> {
|
fn perform(&self, conn: &PgConnection) -> Result<GetPostsResponse, Error> {
|
||||||
let data: &GetPosts = &self.data;
|
let data: &GetPosts = &self.data;
|
||||||
|
|
||||||
if Settings::get().federation_enabled {
|
if Settings::get().federation.enabled {
|
||||||
// TODO: intercept here (but the type is wrong)
|
// TODO: intercept here (but the type is wrong)
|
||||||
//get_remote_community_posts(get_posts.community_id.unwrap())
|
//get_remote_community_posts(get_posts.community_id.unwrap())
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,5 +38,9 @@ fn make_apub_endpoint(endpoint_type: EndpointType, name: &str) -> Url {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_apub_protocol_string() -> &'static str {
|
pub fn get_apub_protocol_string() -> &'static str {
|
||||||
"http"
|
if Settings::get().federation.tls_enabled {
|
||||||
|
"https"
|
||||||
|
} else {
|
||||||
|
"http"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ extern crate reqwest;
|
||||||
|
|
||||||
use crate::api::community::{GetCommunityResponse, ListCommunitiesResponse};
|
use crate::api::community::{GetCommunityResponse, ListCommunitiesResponse};
|
||||||
use crate::api::post::GetPostsResponse;
|
use crate::api::post::GetPostsResponse;
|
||||||
|
use crate::apub::get_apub_protocol_string;
|
||||||
use crate::db::community_view::CommunityView;
|
use crate::db::community_view::CommunityView;
|
||||||
use crate::db::post_view::PostView;
|
use crate::db::post_view::PostView;
|
||||||
use crate::naive_now;
|
use crate::naive_now;
|
||||||
|
@ -16,10 +17,15 @@ use log::warn;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
fn fetch_node_info(domain: &str) -> Result<NodeInfo, Error> {
|
fn fetch_node_info(domain: &str) -> Result<NodeInfo, Error> {
|
||||||
let well_known: NodeInfoWellKnown =
|
let well_known_uri = format!(
|
||||||
reqwest::get(&format!("http://{}/.well-known/nodeinfo", domain))?.json()?;
|
"{}://{}/.well-known/nodeinfo",
|
||||||
Ok(reqwest::get(&well_known.links.href)?.json()?)
|
get_apub_protocol_string(),
|
||||||
|
domain
|
||||||
|
);
|
||||||
|
let well_known = fetch_remote_object::<NodeInfoWellKnown>(&well_known_uri)?;
|
||||||
|
Ok(fetch_remote_object::<NodeInfo>(&well_known.links.href)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch_communities_from_instance(domain: &str) -> Result<Vec<CommunityView>, Error> {
|
fn fetch_communities_from_instance(domain: &str) -> Result<Vec<CommunityView>, Error> {
|
||||||
let node_info = fetch_node_info(domain)?;
|
let node_info = fetch_node_info(domain)?;
|
||||||
if node_info.software.name != "lemmy" {
|
if node_info.software.name != "lemmy" {
|
||||||
|
@ -54,6 +60,9 @@ fn fetch_remote_object<Response>(uri: &str) -> Result<Response, Error>
|
||||||
where
|
where
|
||||||
Response: for<'de> Deserialize<'de>,
|
Response: for<'de> Deserialize<'de>,
|
||||||
{
|
{
|
||||||
|
if Settings::get().federation.tls_enabled && !uri.starts_with("https") {
|
||||||
|
return Err(format_err!("Activitypub uri is insecure: {}", uri));
|
||||||
|
}
|
||||||
// TODO: should cache responses here when we are in production
|
// TODO: should cache responses here when we are in production
|
||||||
// TODO: this function should return a future
|
// TODO: this function should return a future
|
||||||
// TODO: in production mode, fail if protocol is not https
|
// TODO: in production mode, fail if protocol is not https
|
||||||
|
@ -179,11 +188,12 @@ pub fn get_remote_community(identifier: &str) -> Result<GetCommunityResponse, fa
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_following_instances() -> Vec<String> {
|
pub fn get_following_instances() -> Vec<&'static str> {
|
||||||
match Settings::get().federated_instance.clone() {
|
Settings::get()
|
||||||
Some(f) => vec![f, Settings::get().hostname.clone()],
|
.federation
|
||||||
None => vec![Settings::get().hostname.clone()],
|
.followed_instances
|
||||||
}
|
.split(',')
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_all_communities() -> Result<Vec<CommunityView>, Error> {
|
pub fn get_all_communities() -> Result<Vec<CommunityView>, Error> {
|
||||||
|
|
|
@ -9,7 +9,7 @@ use diesel::r2d2::{ConnectionManager, Pool};
|
||||||
use diesel::PgConnection;
|
use diesel::PgConnection;
|
||||||
|
|
||||||
pub fn config(cfg: &mut web::ServiceConfig) {
|
pub fn config(cfg: &mut web::ServiceConfig) {
|
||||||
if Settings::get().federation_enabled {
|
if Settings::get().federation.enabled {
|
||||||
println!("federation enabled, host is {}", Settings::get().hostname);
|
println!("federation enabled, host is {}", Settings::get().hostname);
|
||||||
cfg
|
cfg
|
||||||
.route(
|
.route(
|
||||||
|
|
|
@ -40,7 +40,7 @@ async fn node_info(
|
||||||
Ok(site_view) => site_view,
|
Ok(site_view) => site_view,
|
||||||
Err(_) => return Err(format_err!("not_found")),
|
Err(_) => return Err(format_err!("not_found")),
|
||||||
};
|
};
|
||||||
let protocols = if Settings::get().federation_enabled {
|
let protocols = if Settings::get().federation.enabled {
|
||||||
vec!["activitypub".to_string()]
|
vec!["activitypub".to_string()]
|
||||||
} else {
|
} else {
|
||||||
vec![]
|
vec![]
|
||||||
|
|
|
@ -15,7 +15,7 @@ pub struct Params {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn config(cfg: &mut web::ServiceConfig) {
|
pub fn config(cfg: &mut web::ServiceConfig) {
|
||||||
if Settings::get().federation_enabled {
|
if Settings::get().federation.enabled {
|
||||||
cfg.route(
|
cfg.route(
|
||||||
".well-known/webfinger",
|
".well-known/webfinger",
|
||||||
web::get().to(get_webfinger_response),
|
web::get().to(get_webfinger_response),
|
||||||
|
|
|
@ -17,8 +17,7 @@ pub struct Settings {
|
||||||
pub front_end_dir: String,
|
pub front_end_dir: String,
|
||||||
pub rate_limit: RateLimitConfig,
|
pub rate_limit: RateLimitConfig,
|
||||||
pub email: Option<EmailConfig>,
|
pub email: Option<EmailConfig>,
|
||||||
pub federation_enabled: bool,
|
pub federation: Federation,
|
||||||
pub federated_instance: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
|
@ -50,6 +49,13 @@ pub struct Database {
|
||||||
pub pool_size: u32,
|
pub pool_size: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct Federation {
|
||||||
|
pub enabled: bool,
|
||||||
|
pub followed_instances: String,
|
||||||
|
pub tls_enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref SETTINGS: Settings = {
|
static ref SETTINGS: Settings = {
|
||||||
match Settings::init() {
|
match Settings::init() {
|
||||||
|
|
Reference in a new issue