kanidmd_core/https/
manifest.rsuse axum::http::header::CONTENT_TYPE;
use axum::http::HeaderValue;
use axum::response::{IntoResponse, Response};
use serde::{Deserialize, Serialize};
use serde_with::skip_serializing_none;
use crate::https::extractors::DomainInfo;
const MIME_TYPE_MANIFEST: &str = "application/manifest+json;charset=utf-8";
#[skip_serializing_none]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Manifest {
name: String,
short_name: String,
start_url: String,
#[serde(rename = "display")]
display_mode: DisplayMode,
background_color: String,
description: Option<String>,
#[serde(rename = "dir")]
direction: Direction,
orientation: Option<String>,
lang: Option<String>,
scope: Option<String>,
theme_color: String,
prefer_related_applications: Option<bool>,
icons: Vec<ManifestIcon>,
related_applications: Option<Vec<String>>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
struct ManifestIcon {
src: String,
#[serde(rename = "type")]
mime_type: String,
sizes: String,
#[serde(skip_serializing_if = "Option::is_none")]
purpose: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
enum Direction {
#[serde(rename = "ltr")]
Ltr,
#[serde(rename = "rtl")]
Rtl,
#[serde(rename = "auto")]
Auto,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
enum DisplayMode {
#[serde(rename = "full-screen")]
FullScreen,
#[serde(rename = "standalone")]
Standalone,
#[serde(rename = "minimal-ui")]
MinimalUi,
#[serde(rename = "browser")]
Browser,
}
pub fn manifest_data(host_req: Option<&str>, domain_display_name: String) -> Manifest {
let icons = vec![
ManifestIcon {
sizes: String::from("512x512"),
src: String::from("/pkg/img/logo-square.svg"),
mime_type: String::from("image/svg+xml"),
purpose: None,
},
ManifestIcon {
sizes: String::from("512x512"),
src: String::from("/pkg/img/logo-512.png"),
mime_type: String::from("image/png"),
purpose: Some(String::from("maskable")),
},
ManifestIcon {
sizes: String::from("192x192"),
src: String::from("/pkg/img/logo-192.png"),
mime_type: String::from("image/png"),
purpose: Some(String::from("maskable")),
},
ManifestIcon {
sizes: String::from("256x156"),
src: String::from("/pkg/img/logo-256.png"),
mime_type: String::from("image/png"),
purpose: Some(String::from("maskable")),
},
];
let start_url = match host_req {
Some(value) => format!("https://{}/", value),
None => String::from("/"),
};
Manifest {
short_name: "Kanidm".to_string(),
name: domain_display_name,
start_url,
display_mode: DisplayMode::MinimalUi,
description: None,
orientation: None,
lang: Some("en".to_string()),
theme_color: "white".to_string(),
background_color: "white".to_string(),
direction: Direction::Auto,
scope: None,
prefer_related_applications: None,
icons,
related_applications: None,
}
}
pub(crate) async fn manifest(DomainInfo(domain_info): DomainInfo) -> impl IntoResponse {
let domain_display_name = domain_info.display_name().to_string();
let manifest_string =
serde_json::to_string_pretty(&manifest_data(None, domain_display_name)).unwrap_or_default();
let mut res = Response::new(manifest_string);
res.headers_mut()
.insert(CONTENT_TYPE, HeaderValue::from_static(MIME_TYPE_MANIFEST));
res
}