1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-08-07 17:03:01 +03:00

Mount the static assets on /assets

This commit is contained in:
Quentin Gliech
2022-09-30 15:31:47 +02:00
parent eeae943208
commit 93ce5c797c
8 changed files with 92 additions and 24 deletions

View File

@@ -27,7 +27,7 @@ use mas_email::Mailer;
use mas_handlers::{AppState, MatrixHomeserver};
use mas_http::ServerLayer;
use mas_policy::PolicyFactory;
use mas_router::UrlBuilder;
use mas_router::{Route, UrlBuilder};
use mas_storage::MIGRATOR;
use mas_tasks::TaskQueue;
use mas_templates::Templates;
@@ -201,8 +201,14 @@ impl Options {
.context("failed to load the policy")?;
let policy_factory = Arc::new(policy_factory);
let url_builder = UrlBuilder::new(config.http.public_base.clone());
// Load and compile the templates
let templates = Templates::load(config.templates.path.clone(), config.templates.builtin)
let templates = Templates::load(
config.templates.path.clone(),
config.templates.builtin,
url_builder.clone(),
)
.await
.context("could not load templates")?;
@@ -213,8 +219,6 @@ impl Options {
&config.email.reply_to,
);
let url_builder = UrlBuilder::new(config.http.public_base.clone());
let static_files = mas_static_files::service(&config.http.web_root);
let homeserver = MatrixHomeserver::new(config.matrix.homeserver.clone());
@@ -246,7 +250,7 @@ impl Options {
};
let router = mas_handlers::router(state)
.fallback_service(static_files)
.nest(mas_router::StaticAsset::route(), static_files)
.layer(ServerLayer::default());
info!("Listening on http://{}", listener.local_addr().unwrap());

View File

@@ -15,7 +15,6 @@
use std::path::PathBuf;
use clap::Parser;
use mas_config::TemplatesConfig;
use mas_templates::Templates;
#[derive(Parser, Debug)]
@@ -58,11 +57,9 @@ impl Options {
}
SC::Check { path, skip_builtin } => {
let config = TemplatesConfig {
path: Some(path.to_string()),
builtin: !skip_builtin,
};
let templates = Templates::load(config.path.clone(), config.builtin).await?;
let url_builder = mas_router::UrlBuilder::new("https://example.com/".parse()?);
let templates =
Templates::load(Some(path.into()), !skip_builtin, url_builder).await?;
templates.check_render().await?;
Ok(())

View File

@@ -280,7 +280,9 @@ where
async fn test_state(pool: PgPool) -> Result<Arc<AppState>, anyhow::Error> {
use mas_email::MailTransport;
let templates = Templates::load(None, true).await?;
let url_builder = UrlBuilder::new("https://example.com/".parse()?);
let templates = Templates::load(None, true, url_builder.clone()).await?;
// TODO: add test keys to the store
let key_store = Keystore::default();
@@ -291,8 +293,6 @@ async fn test_state(pool: PgPool) -> Result<Arc<AppState>, anyhow::Error> {
let mailbox = "server@example.com".parse()?;
let mailer = Mailer::new(&templates, &transport, &mailbox, &mailbox);
let url_builder = UrlBuilder::new("https://example.com/".parse()?);
let homeserver = MatrixHomeserver::new("example.com".to_owned());
let policy_factory = PolicyFactory::load_default(serde_json::json!({})).await?;
let policy_factory = Arc::new(policy_factory);

View File

@@ -522,3 +522,26 @@ impl Route for CompatLoginSsoComplete {
format!("/complete-compat-sso/{}", self.id).into()
}
}
/// `GET /assets`
pub struct StaticAsset {
path: String,
}
impl StaticAsset {
#[must_use]
pub fn new(path: String) -> Self {
Self { path }
}
}
impl Route for StaticAsset {
type Query = ();
fn route() -> &'static str {
"/assets"
}
fn path(&self) -> std::borrow::Cow<'static, str> {
format!("/assets/{}", self.path).into()
}
}

View File

@@ -91,4 +91,10 @@ impl UrlBuilder {
pub fn jwks_uri(&self) -> Url {
self.url_for(&crate::endpoints::OAuth2Keys)
}
/// Static asset
#[must_use]
pub fn static_asset(&self, path: String) -> Url {
self.url_for(&crate::endpoints::StaticAsset::new(path))
}
}

View File

@@ -16,14 +16,16 @@
use std::{collections::HashMap, str::FromStr};
use mas_router::{Route, UrlBuilder};
use tera::{helpers::tests::number_args_allowed, Tera, Value};
use url::Url;
pub fn register(tera: &mut Tera) {
pub fn register(tera: &mut Tera, url_builder: UrlBuilder) {
tera.register_tester("empty", self::tester_empty);
tera.register_function("add_params_to_uri", function_add_params_to_uri);
tera.register_function("merge", function_merge);
tera.register_function("dict", function_dict);
tera.register_function("static_asset", make_static_asset(url_builder));
}
fn tester_empty(value: Option<&Value>, params: &[Value]) -> Result<bool, tera::Error> {
@@ -115,3 +117,26 @@ fn function_dict(params: &HashMap<String, Value>) -> Result<Value, tera::Error>
let ret = params.clone().into_iter().collect();
Ok(Value::Object(ret))
}
fn make_static_asset(url_builder: UrlBuilder) -> impl tera::Function {
Box::new(
move |args: &HashMap<String, Value>| -> Result<Value, tera::Error> {
if let Some(path) = args.get("path").and_then(Value::as_str) {
let absolute = args
.get("absolute")
.and_then(Value::as_bool)
.unwrap_or(false);
let path = path.to_owned();
let url = if absolute {
url_builder.static_asset(path).into()
} else {
let destination = mas_router::StaticAsset::new(path);
destination.relative_url().into_owned()
};
Ok(Value::String(url))
} else {
Err(tera::Error::msg("Invalid parameter 'path'"))
}
},
)
}

View File

@@ -34,6 +34,7 @@ use std::{
use anyhow::{bail, Context as _};
use mas_data_model::StorageBackend;
use mas_router::UrlBuilder;
use serde::Serialize;
use tera::{Context, Error as TeraError, Tera};
use thiserror::Error;
@@ -62,6 +63,7 @@ pub use self::{
#[derive(Debug, Clone)]
pub struct Templates {
tera: Arc<RwLock<Tera>>,
url_builder: UrlBuilder,
path: Option<String>,
builtin: bool,
}
@@ -134,16 +136,25 @@ impl Templates {
}
/// Load the templates from the given config
pub async fn load(path: Option<String>, builtin: bool) -> Result<Self, TemplateLoadingError> {
let tera = Self::load_(path.as_deref(), builtin).await?;
pub async fn load(
path: Option<String>,
builtin: bool,
url_builder: UrlBuilder,
) -> Result<Self, TemplateLoadingError> {
let tera = Self::load_(path.as_deref(), builtin, url_builder.clone()).await?;
Ok(Self {
tera: Arc::new(RwLock::new(tera)),
path,
url_builder,
builtin,
})
}
async fn load_(path: Option<&str>, builtin: bool) -> Result<Tera, TemplateLoadingError> {
async fn load_(
path: Option<&str>,
builtin: bool,
url_builder: UrlBuilder,
) -> Result<Tera, TemplateLoadingError> {
let mut teras = Vec::new();
let roots = Self::roots(path, builtin).await;
@@ -183,7 +194,7 @@ impl Templates {
tera.build_inheritance_chains()?;
tera.check_macro_files()?;
self::functions::register(&mut tera);
self::functions::register(&mut tera, url_builder);
let loaded: HashSet<_> = tera.get_template_names().collect();
let needed: HashSet<_> = TEMPLATES.into_iter().map(|(name, _)| name).collect();
@@ -202,7 +213,8 @@ impl Templates {
/// Reload the templates on disk
pub async fn reload(&self) -> anyhow::Result<()> {
// Prepare the new Tera instance
let new_tera = Self::load_(self.path.as_deref(), self.builtin).await?;
let new_tera =
Self::load_(self.path.as_deref(), self.builtin, self.url_builder.clone()).await?;
// Swap it
*self.tera.write().await = new_tera;
@@ -378,7 +390,8 @@ mod tests {
#[tokio::test]
async fn check_builtin_templates() {
let templates = Templates::load(None, true).await.unwrap();
let url_builder = UrlBuilder::new("https://example.com/".parse().unwrap());
let templates = Templates::load(None, true, url_builder).await.unwrap();
templates.check_render().await.unwrap();
}
}

View File

@@ -27,7 +27,7 @@ limitations under the License.
<meta charset="utf-8">
<title>{% block title %}matrix-authentication-service{% endblock title %}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/tailwind.css">
<link rel="stylesheet" href="{{ static_asset(path='tailwind.css') }}">
</head>
<body class="bg-white text-black-900 dark:bg-black-800 dark:text-white flex flex-col min-h-screen">
{% block content %}{% endblock content %}