aboutsummaryrefslogtreecommitdiffstats
path: root/src/config
diff options
context:
space:
mode:
Diffstat (limited to 'src/config')
-rw-r--r--src/config/mod.rs19
1 files changed, 19 insertions, 0 deletions
diff --git a/src/config/mod.rs b/src/config/mod.rs
index 60ad413..f0e5dc5 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -138,6 +138,13 @@ pub(crate) const OPTIONS: &[OptionSpec] = &[
"How long after a login (POST /auth/login) its tokens may be refreshed; then the user logs in again.",
),
option(
+ "cors-origins",
+ Kind::List,
+ "ORIGIN,[ORIGIN...]",
+ None,
+ "Origins (scheme://host[:port]) whose pages may read this node's own links and refresh tokens here, with a token (docs/access.md, Tokens): the dashboards of other members are allowed anyway, as the member list names them (dashboard-url). Without credentials: a page sends its token itself.",
+ ),
+ option(
"bootstrap-users",
Kind::List,
"USER,[USER...]",
@@ -557,6 +564,8 @@ pub(crate) struct Settings {
pub(crate) protocol_writers: Vec<String>,
#[serde(default)]
pub(crate) bootstrap_users: Vec<String>,
+ #[serde(default)]
+ pub(crate) cors_origins: Vec<String>,
#[serde(
default = "default_token_lifetime",
with = "crate::units::duration_option"
@@ -790,6 +799,16 @@ impl Settings {
if self.remake.is_some() && !self.genesis {
bail!("remake makes a new swarm's document; it needs genesis");
}
+ if let Some(bad) = self.cors_origins.iter().find(|origin| {
+ url::Url::parse(origin)
+ .ok()
+ .filter(|url| url.origin().is_tuple())
+ .is_none_or(|url| url.origin().ascii_serialization() != **origin)
+ }) {
+ bail!(
+ "cors-origins: {bad:?} isn't an origin (scheme://host[:port], no path; * isn't taken)"
+ );
+ }
if !self.bootstrap_users.is_empty() && !self.genesis {
bail!(
"bootstrap-users names the first users of a new swarm; it needs genesis (drop it once the swarm exists)"