mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 13:05:32 +09:00
fix(admin): use instance branding on self-hosted (#3401)
This commit is contained in:
1 parent
af7724dbf6
commit
50c28aa8fa
9 files changed
+206
-49
No files matched your search
@@ -1,6 +1,10 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use crate::{api::types::FlashLevel, config::AdminConfig, middleware::auth::AuthContext};
|
||||
use crate::{
|
||||
api::types::{FlashLevel, PremiumBranding},
|
||||
config::AdminConfig,
|
||||
middleware::auth::AuthContext,
|
||||
};
|
||||
use maud::{DOCTYPE, Markup, PreEscaped, html};
|
||||
|
||||
use super::components::drawer::drawer_controller_script;
|
||||
@@ -11,6 +15,28 @@ use super::layout_scripts::{
|
||||
};
|
||||
use super::layout_sidebar::render_sidebar;
|
||||
|
||||
const DEFAULT_PRODUCT_NAME: &str = "Fluxer";
|
||||
|
||||
pub fn product_name(branding: Option<&PremiumBranding>) -> &str {
|
||||
branding
|
||||
.and_then(|branding| branding.product_name.as_deref())
|
||||
.unwrap_or(DEFAULT_PRODUCT_NAME)
|
||||
}
|
||||
|
||||
pub fn favicon_links(config: &AdminConfig, branding: Option<&PremiumBranding>) -> Markup {
|
||||
let cdn = &config.static_cdn_endpoint;
|
||||
html! {
|
||||
@if let Some(favicon_url) = branding.and_then(|branding| branding.favicon_url.as_deref()) {
|
||||
link rel="icon" href=(favicon_url);
|
||||
} @else {
|
||||
link rel="icon" type="image/x-icon" href={(cdn) "/web/favicon.ico"};
|
||||
link rel="apple-touch-icon" href={(cdn) "/web/apple-touch-icon.png"};
|
||||
link rel="icon" type="image/png" sizes="32x32" href={(cdn) "/web/favicon-32x32.png"};
|
||||
link rel="icon" type="image/png" sizes="16x16" href={(cdn) "/web/favicon-16x16.png"};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn cache_busted_asset(base_path: &str, asset_version: &str, path: &str) -> String {
|
||||
format!("{base_path}{path}?t={asset_version}")
|
||||
}
|
||||
@@ -72,10 +98,7 @@ pub fn admin_layout_ext(
|
||||
title { (title) " ~ Fluxer Admin" }
|
||||
link rel="stylesheet" href={(base) "/static/fonts/" (crate::fonts::STYLESHEET_FILE_NAME)};
|
||||
link rel="stylesheet" href=(cache_busted_asset(base, asset_version, "/static/app.css"));
|
||||
link rel="icon" type="image/x-icon" href={(config.static_cdn_endpoint) "/web/favicon.ico"};
|
||||
link rel="apple-touch-icon" href={(config.static_cdn_endpoint) "/web/apple-touch-icon.png"};
|
||||
link rel="icon" type="image/png" sizes="32x32" href={(config.static_cdn_endpoint) "/web/favicon-32x32.png"};
|
||||
link rel="icon" type="image/png" sizes="16x16" href={(config.static_cdn_endpoint) "/web/favicon-16x16.png"};
|
||||
(favicon_links(config, auth.branding.as_ref()))
|
||||
script src=(cache_busted_asset(base, asset_version, "/static/htmx.min.js")) defer {}
|
||||
}
|
||||
body class="min-h-screen overflow-hidden bg-neutral-50" hx-boost="true" {
|
||||
@@ -126,3 +149,53 @@ fn render_flash(flash: &crate::api::types::FlashMessage) -> Markup {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::config::ProxyConfig;
|
||||
|
||||
fn config() -> AdminConfig {
|
||||
AdminConfig {
|
||||
host: String::new(),
|
||||
port: 3020,
|
||||
secret_key_base: "test-secret".to_owned(),
|
||||
base_path: String::new(),
|
||||
api_endpoint: String::new(),
|
||||
media_endpoint: String::new(),
|
||||
static_cdn_endpoint: "https://static.example".to_owned(),
|
||||
reports_bucket_origin: String::new(),
|
||||
admin_endpoint: String::new(),
|
||||
web_app_endpoint: String::new(),
|
||||
oauth_client_id: String::new(),
|
||||
oauth_client_secret: String::new(),
|
||||
oauth_redirect_uri: String::new(),
|
||||
build_version: "test".to_owned(),
|
||||
self_hosted: true,
|
||||
proxy: ProxyConfig {
|
||||
trust_client_ip_header: false,
|
||||
client_ip_header_name: String::new(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn instance_branding_replaces_the_fluxer_name_and_favicons() {
|
||||
let branding = PremiumBranding {
|
||||
product_name: Some("Example".to_owned()),
|
||||
favicon_url: Some("https://media.example/favicon.png".to_owned()),
|
||||
..PremiumBranding::default()
|
||||
};
|
||||
let links = favicon_links(&config(), Some(&branding)).into_string();
|
||||
assert!(links.contains("https://media.example/favicon.png"));
|
||||
assert!(!links.contains("static.example"));
|
||||
assert_eq!(product_name(Some(&branding)), "Example");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn missing_branding_keeps_the_fluxer_name_and_favicons() {
|
||||
let links = favicon_links(&config(), Some(&PremiumBranding::default())).into_string();
|
||||
assert!(links.contains("https://static.example/web/favicon.ico"));
|
||||
assert_eq!(product_name(None), "Fluxer");
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,17 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
use crate::config::AdminConfig;
|
||||
use crate::{
|
||||
api::types::PremiumBranding,
|
||||
config::AdminConfig,
|
||||
templates::layout::{favicon_links, product_name},
|
||||
};
|
||||
use maud::{DOCTYPE, Markup, html};
|
||||
|
||||
pub fn login_page(config: &AdminConfig, error_message: Option<&str>) -> Markup {
|
||||
pub fn login_page(
|
||||
config: &AdminConfig,
|
||||
branding: Option<&PremiumBranding>,
|
||||
error_message: Option<&str>,
|
||||
) -> Markup {
|
||||
let base = &config.base_path;
|
||||
html! {
|
||||
(DOCTYPE)
|
||||
@@ -14,7 +22,7 @@ pub fn login_page(config: &AdminConfig, error_message: Option<&str>) -> Markup {
|
||||
title { "Login ~ Fluxer Admin" }
|
||||
link rel="stylesheet" href={(base) "/static/fonts/" (crate::fonts::STYLESHEET_FILE_NAME)};
|
||||
link rel="stylesheet" href={(base) "/static/app.css"};
|
||||
link rel="icon" type="image/x-icon" href={(config.static_cdn_endpoint) "/web/favicon.ico"};
|
||||
(favicon_links(config, branding))
|
||||
}
|
||||
body class="flex min-h-[100dvh] items-center justify-center bg-neutral-50 p-4" {
|
||||
main class="w-full max-w-sm" {
|
||||
@@ -38,7 +46,7 @@ pub fn login_page(config: &AdminConfig, error_message: Option<&str>) -> Markup {
|
||||
bg-neutral-900 text-white hover:bg-neutral-800 \
|
||||
px-4 py-2 text-base w-full sm:w-fit \
|
||||
focus:ring-offset-white" {
|
||||
span { "Sign in with Fluxer" }
|
||||
span { "Sign in with " (product_name(branding)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::{
|
||||
},
|
||||
page_container::{card, page_header},
|
||||
},
|
||||
layout::admin_layout,
|
||||
layout::{admin_layout, product_name},
|
||||
},
|
||||
};
|
||||
use maud::{Markup, html};
|
||||
@@ -37,9 +37,9 @@ pub fn system_dm_page(
|
||||
"Send a system DM"
|
||||
}
|
||||
p class="text-sm text-neutral-500" {
|
||||
"Sent from the official Fluxer system account. Each recipient \
|
||||
will receive the same content as a DM. Progress is observable \
|
||||
on the "
|
||||
"Sent from the official " (product_name(auth.branding.as_ref()))
|
||||
" system account. Each recipient will receive the same content \
|
||||
as a DM. Progress is observable on the "
|
||||
a href=(jobs_url) class="font-medium text-neutral-900 hover:underline" {
|
||||
"Jobs page"
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user