Skip to content
This repository was archived by the owner on Sep 10, 2024. It is now read-only.

Add instance privacy policy, TOS and imprint, and loads of design cleanups #2006

Merged
merged 4 commits into from
Oct 30, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add instance privacy policy, TOS and imprint, and loads of design cle…
…anups
sandhose committed Oct 27, 2023
commit 0473e35e5a6725fe14361461e2b0fea7564eb2b7
4 changes: 1 addition & 3 deletions crates/axum-utils/src/language_detection.rs
Original file line number Diff line number Diff line change
@@ -30,9 +30,7 @@ struct AcceptLanguagePart {

impl PartialOrd for AcceptLanguagePart {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
// When comparing two AcceptLanguage structs, we only consider the
// quality, in reverse.
Reverse(self.quality).partial_cmp(&Reverse(other.quality))
Some(self.cmp(other))
}
}

8 changes: 7 additions & 1 deletion crates/cli/src/commands/server.rs
Original file line number Diff line number Diff line change
@@ -93,7 +93,13 @@ impl Options {
);

// Load and compile the templates
let templates = templates_from_config(&config.templates, &url_builder).await?;
let templates = templates_from_config(
&config.templates,
&config.branding,
&url_builder,
&config.matrix.homeserver,
)
.await?;

let http_client_factory = HttpClientFactory::new().await?;

15 changes: 12 additions & 3 deletions crates/cli/src/commands/templates.rs
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@
// limitations under the License.

use clap::Parser;
use mas_config::TemplatesConfig;
use mas_config::{BrandingConfig, MatrixConfig, TemplatesConfig};
use mas_storage::{Clock, SystemClock};
use rand::SeedableRng;
use tracing::info_span;
@@ -39,13 +39,22 @@ impl Options {
SC::Check => {
let _span = info_span!("cli.templates.check").entered();

let config: TemplatesConfig = root.load_config()?;
let template_config: TemplatesConfig = root.load_config()?;
let branding_config: BrandingConfig = root.load_config()?;
let matrix_config: MatrixConfig = root.load_config()?;

let clock = SystemClock::default();
// XXX: we should disallow SeedableRng::from_entropy
let mut rng = rand_chacha::ChaChaRng::from_entropy();
let url_builder =
mas_router::UrlBuilder::new("https://example.com/".parse()?, None, None);
let templates = templates_from_config(&config, &url_builder).await?;
let templates = templates_from_config(
&template_config,
&branding_config,
&url_builder,
&matrix_config.homeserver,
)
.await?;
templates.check_render(clock.now(), &mut rng)?;

Ok(())
8 changes: 7 additions & 1 deletion crates/cli/src/commands/worker.rs
Original file line number Diff line number Diff line change
@@ -44,7 +44,13 @@ impl Options {
);

// Load and compile the templates
let templates = templates_from_config(&config.templates, &url_builder).await?;
let templates = templates_from_config(
&config.templates,
&config.branding,
&url_builder,
&config.matrix.homeserver,
)
.await?;

let mailer = mailer_from_config(&config.email, &templates)?;
mailer.test_connection().await?;
27 changes: 24 additions & 3 deletions crates/cli/src/util.rs
Original file line number Diff line number Diff line change
@@ -16,14 +16,14 @@ use std::time::Duration;

use anyhow::Context;
use mas_config::{
DatabaseConfig, DatabaseConnectConfig, EmailConfig, EmailSmtpMode, EmailTransportConfig,
PasswordsConfig, PolicyConfig, TemplatesConfig,
BrandingConfig, DatabaseConfig, DatabaseConnectConfig, EmailConfig, EmailSmtpMode,
EmailTransportConfig, PasswordsConfig, PolicyConfig, TemplatesConfig,
};
use mas_email::{MailTransport, Mailer};
use mas_handlers::{passwords::PasswordManager, ActivityTracker};
use mas_policy::PolicyFactory;
use mas_router::UrlBuilder;
use mas_templates::{TemplateLoadingError, Templates};
use mas_templates::{SiteBranding, TemplateLoadingError, Templates};
use sqlx::{
postgres::{PgConnectOptions, PgPoolOptions},
ConnectOptions, PgConnection, PgPool,
@@ -116,13 +116,34 @@ pub async fn policy_factory_from_config(

pub async fn templates_from_config(
config: &TemplatesConfig,
branding: &BrandingConfig,
url_builder: &UrlBuilder,
server_name: &str,
) -> Result<Templates, TemplateLoadingError> {
let mut site_branding = SiteBranding::new(server_name);

if let Some(service_name) = branding.service_name.as_deref() {
site_branding = site_branding.with_service_name(service_name);
}

if let Some(policy_uri) = &branding.policy_uri {
site_branding = site_branding.with_policy_uri(policy_uri.as_str());
}

if let Some(tos_uri) = &branding.tos_uri {
site_branding = site_branding.with_tos_uri(tos_uri.as_str());
}

if let Some(imprint) = branding.imprint.as_deref() {
site_branding = site_branding.with_imprint(imprint);
}

Templates::load(
config.path.clone(),
url_builder.clone(),
config.assets_manifest.clone(),
config.translations_path.clone(),
site_branding,
)
.await
}
63 changes: 63 additions & 0 deletions crates/config/src/sections/branding.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright 2023 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use async_trait::async_trait;
use rand::Rng;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use url::Url;

use crate::ConfigurationSection;

/// Configuration section for tweaking the branding of the service
#[derive(Clone, Debug, Deserialize, JsonSchema, Serialize, Default)]
pub struct BrandingConfig {
/// A human-readable name. Defaults to the server's address.
pub service_name: Option<String>,

/// Link to a privacy policy, displayed in the footer of web pages and
/// emails. It is also advertised to clients through the `op_policy_uri`
/// OIDC provider metadata.
pub policy_uri: Option<Url>,

/// Link to a terms of service document, displayed in the footer of web
/// pages and emails. It is also advertised to clients through the
/// `op_tos_uri` OIDC provider metadata.
pub tos_uri: Option<Url>,

/// Legal imprint, displayed in the footer in the footer of web pages and
/// emails.
pub imprint: Option<String>,

/// Logo displayed in some web pages.
pub logo_uri: Option<Url>,
}

#[async_trait]
impl ConfigurationSection for BrandingConfig {
fn path() -> &'static str {
"branding"
}

async fn generate<R>(_rng: R) -> anyhow::Result<Self>
where
R: Rng + Send,
{
Ok(Self::default())
}

fn test() -> Self {
Self::default()
}
}
13 changes: 13 additions & 0 deletions crates/config/src/sections/mod.rs
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@ use rand::Rng;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

mod branding;
mod clients;
mod database;
mod email;
@@ -31,6 +32,7 @@ mod templates;
mod upstream_oauth2;

pub use self::{
branding::BrandingConfig,
clients::{ClientAuthMethodConfig, ClientConfig, ClientsConfig},
database::{ConnectConfig as DatabaseConnectConfig, DatabaseConfig},
email::{EmailConfig, EmailSmtpMode, EmailTransportConfig},
@@ -103,6 +105,10 @@ pub struct RootConfig {
#[serde(default)]
pub upstream_oauth2: UpstreamOAuth2Config,

/// Configuration section for tweaking the branding of the service
#[serde(default)]
pub branding: BrandingConfig,

/// Experimental configuration options
#[serde(default)]
pub experimental: ExperimentalConfig,
@@ -130,6 +136,7 @@ impl ConfigurationSection for RootConfig {
matrix: MatrixConfig::generate(&mut rng).await?,
policy: PolicyConfig::generate(&mut rng).await?,
upstream_oauth2: UpstreamOAuth2Config::generate(&mut rng).await?,
branding: BrandingConfig::generate(&mut rng).await?,
experimental: ExperimentalConfig::generate(&mut rng).await?,
})
}
@@ -147,6 +154,7 @@ impl ConfigurationSection for RootConfig {
matrix: MatrixConfig::test(),
policy: PolicyConfig::test(),
upstream_oauth2: UpstreamOAuth2Config::test(),
branding: BrandingConfig::test(),
experimental: ExperimentalConfig::test(),
}
}
@@ -178,6 +186,9 @@ pub struct AppConfig {
#[serde(default)]
pub policy: PolicyConfig,

#[serde(default)]
pub branding: BrandingConfig,

#[serde(default)]
pub experimental: ExperimentalConfig,
}
@@ -201,6 +212,7 @@ impl ConfigurationSection for AppConfig {
secrets: SecretsConfig::generate(&mut rng).await?,
matrix: MatrixConfig::generate(&mut rng).await?,
policy: PolicyConfig::generate(&mut rng).await?,
branding: BrandingConfig::generate(&mut rng).await?,
experimental: ExperimentalConfig::generate(&mut rng).await?,
})
}
@@ -215,6 +227,7 @@ impl ConfigurationSection for AppConfig {
secrets: SecretsConfig::test(),
matrix: MatrixConfig::test(),
policy: PolicyConfig::test(),
branding: BrandingConfig::test(),
experimental: ExperimentalConfig::test(),
}
}
5 changes: 4 additions & 1 deletion crates/handlers/src/test_utils.rs
Original file line number Diff line number Diff line change
@@ -40,7 +40,7 @@ use mas_policy::{InstantiateError, Policy, PolicyFactory};
use mas_router::{SimpleRoute, UrlBuilder};
use mas_storage::{clock::MockClock, BoxClock, BoxRepository, BoxRng, Repository};
use mas_storage_pg::{DatabaseError, PgRepository};
use mas_templates::Templates;
use mas_templates::{SiteBranding, Templates};
use rand::SeedableRng;
use rand_chacha::ChaChaRng;
use serde::{de::DeserializeOwned, Serialize};
@@ -116,11 +116,14 @@ impl TestState {

let url_builder = UrlBuilder::new("https://example.com/".parse()?, None, None);

let site_branding = SiteBranding::new("example.com").with_service_name("Example");

let templates = Templates::load(
workspace_root.join("templates"),
url_builder.clone(),
workspace_root.join("frontend/dist/manifest.json"),
workspace_root.join("translations"),
site_branding,
)
.await?;

4 changes: 2 additions & 2 deletions crates/matrix-synapse/src/lib.rs
Original file line number Diff line number Diff line change
@@ -54,8 +54,8 @@ impl SynapseConnection {
.uri(
self.endpoint
.join(url)
.map(Url::into)
.unwrap_or(String::new()),
.map(String::from)
.unwrap_or_default(),
)
.header(AUTHORIZATION, format!("Bearer {}", self.access_token))
}
4 changes: 2 additions & 2 deletions crates/router/src/traits.rs
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::borrow::{Borrow, Cow};
use std::borrow::Cow;

use serde::Serialize;
use url::Url;
@@ -41,7 +41,7 @@ pub trait Route {
fn absolute_url(&self, base: &Url) -> Url {
let relative = self.path_and_query();
let relative = relative.trim_start_matches('/');
base.join(relative.borrow()).unwrap()
base.join(relative).unwrap()
}
}

3 changes: 3 additions & 0 deletions crates/templates/src/context.rs
Original file line number Diff line number Diff line change
@@ -14,6 +14,8 @@

//! Contexts used in templates

mod branding;

use std::fmt::Formatter;

use chrono::{DateTime, Utc};
@@ -29,6 +31,7 @@ use serde::{ser::SerializeStruct, Deserialize, Serialize};
use ulid::Ulid;
use url::Url;

pub use self::branding::SiteBranding;
use crate::{FormField, FormState};

/// Helper trait to construct context wrappers
Loading