mirror of
https://github.com/dani-garcia/vaultwarden
synced 2024-11-24 21:03:05 +00:00
use a custom 404 page
to customize the 404 page you can copy the handlebar template `src/static/templates/404.hbs` to the TEMPLATES_FOLDER (defaults to `data/templates/`)
This commit is contained in:
parent
1b56f4266b
commit
d209df9e10
5 changed files with 167 additions and 5 deletions
93
resources/404.svg
Normal file
93
resources/404.svg
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="500"
|
||||||
|
height="222"
|
||||||
|
viewBox="0 0 500 222"
|
||||||
|
version="1.1"
|
||||||
|
id="svg5"
|
||||||
|
xml:space="preserve"
|
||||||
|
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14, custom)"
|
||||||
|
sodipodi:docname="404.svg"
|
||||||
|
inkscape:export-filename="404.png"
|
||||||
|
inkscape:export-xdpi="96"
|
||||||
|
inkscape:export-ydpi="96"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||||
|
id="namedview7"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="1.3791767"
|
||||||
|
inkscape:cx="284.59007"
|
||||||
|
inkscape:cy="214.25826"
|
||||||
|
inkscape:window-width="1916"
|
||||||
|
inkscape:window-height="1038"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="18"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showguides="false" /><defs
|
||||||
|
id="defs2"><mask
|
||||||
|
id="holes"><rect
|
||||||
|
x="-60"
|
||||||
|
y="-60"
|
||||||
|
width="120"
|
||||||
|
height="120"
|
||||||
|
fill="#ffffff"
|
||||||
|
id="rect3296" /><circle
|
||||||
|
id="hole"
|
||||||
|
cy="-40"
|
||||||
|
r="3"
|
||||||
|
cx="0" /><use
|
||||||
|
transform="rotate(72)"
|
||||||
|
xlink:href="#hole"
|
||||||
|
id="use3299" /><use
|
||||||
|
transform="rotate(144)"
|
||||||
|
xlink:href="#hole"
|
||||||
|
id="use3301" /><use
|
||||||
|
transform="rotate(-144)"
|
||||||
|
xlink:href="#hole"
|
||||||
|
id="use3303" /><use
|
||||||
|
transform="rotate(-72)"
|
||||||
|
xlink:href="#hole"
|
||||||
|
id="use3305" /></mask></defs><g
|
||||||
|
inkscape:label="Ebene 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"><rect
|
||||||
|
style="fill:none;fill-opacity:0.5;stroke:none;stroke-width:0.74;stroke-opacity:1"
|
||||||
|
id="rect681"
|
||||||
|
width="666"
|
||||||
|
height="222"
|
||||||
|
x="0"
|
||||||
|
y="0" /><text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:128px;line-height:1.25;font-family:'Open Sans';-inkscape-font-specification:'Open Sans';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:0.7;stroke-width:1"
|
||||||
|
x="249.9375"
|
||||||
|
y="134.8125"
|
||||||
|
id="text3425"><tspan
|
||||||
|
id="tspan3423"
|
||||||
|
x="249.9375"
|
||||||
|
y="134.8125"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:128px;font-family:'Open Sans';-inkscape-font-specification:'Open Sans';text-align:center;text-anchor:middle;fill:#000000;fill-opacity:0.7;stroke-width:1"
|
||||||
|
sodipodi:role="line">404</tspan></text><text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-size:26.6667px;line-height:1.25;font-family:'Open Sans';-inkscape-font-specification:'Open Sans';text-align:center;text-anchor:middle"
|
||||||
|
x="249.04297"
|
||||||
|
y="194.68582"
|
||||||
|
id="text4067"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan4065"
|
||||||
|
x="249.04295"
|
||||||
|
y="194.68582"
|
||||||
|
style="font-size:26.6667px;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:0.7">Return to the web vault?</tspan></text></g></svg>
|
After Width: | Height: | Size: 3.3 KiB |
|
@ -1,11 +1,10 @@
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use rocket::serde::json::Json;
|
use rocket::{fs::NamedFile, http::ContentType, response::content::RawHtml as Html, serde::json::Json, Catcher, Route};
|
||||||
use rocket::{fs::NamedFile, http::ContentType, Catcher, Route};
|
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
api::core::now,
|
api::{core::now, ApiResult},
|
||||||
error::Error,
|
error::Error,
|
||||||
util::{Cached, SafeString},
|
util::{Cached, SafeString},
|
||||||
CONFIG,
|
CONFIG,
|
||||||
|
@ -30,8 +29,13 @@ pub fn catchers() -> Vec<Catcher> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[catch(404)]
|
#[catch(404)]
|
||||||
async fn not_found() -> Cached<Option<NamedFile>> {
|
fn not_found() -> ApiResult<Html<String>> {
|
||||||
Cached::short(NamedFile::open(Path::new(&CONFIG.web_vault_folder()).join("404.html")).await.ok(), false)
|
// Return the page
|
||||||
|
let json = json!({
|
||||||
|
"urlpath": CONFIG.domain_path()
|
||||||
|
});
|
||||||
|
let text = CONFIG.render_template("404", &json)?;
|
||||||
|
Ok(Html(text))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
|
@ -91,6 +95,7 @@ fn alive(_conn: DbConn) -> Json<String> {
|
||||||
#[get("/vw_static/<filename>")]
|
#[get("/vw_static/<filename>")]
|
||||||
pub fn static_files(filename: String) -> Result<(ContentType, &'static [u8]), Error> {
|
pub fn static_files(filename: String) -> Result<(ContentType, &'static [u8]), Error> {
|
||||||
match filename.as_ref() {
|
match filename.as_ref() {
|
||||||
|
"404.png" => Ok((ContentType::PNG, include_bytes!("../static/images/404.png"))),
|
||||||
"mail-github.png" => Ok((ContentType::PNG, include_bytes!("../static/images/mail-github.png"))),
|
"mail-github.png" => Ok((ContentType::PNG, include_bytes!("../static/images/mail-github.png"))),
|
||||||
"logo-gray.png" => Ok((ContentType::PNG, include_bytes!("../static/images/logo-gray.png"))),
|
"logo-gray.png" => Ok((ContentType::PNG, include_bytes!("../static/images/logo-gray.png"))),
|
||||||
"error-x.svg" => Ok((ContentType::SVG, include_bytes!("../static/images/error-x.svg"))),
|
"error-x.svg" => Ok((ContentType::SVG, include_bytes!("../static/images/error-x.svg"))),
|
||||||
|
|
|
@ -1123,6 +1123,8 @@ where
|
||||||
reg!("admin/organizations");
|
reg!("admin/organizations");
|
||||||
reg!("admin/diagnostics");
|
reg!("admin/diagnostics");
|
||||||
|
|
||||||
|
reg!("404");
|
||||||
|
|
||||||
// And then load user templates to overwrite the defaults
|
// And then load user templates to overwrite the defaults
|
||||||
// Use .hbs extension for the files
|
// Use .hbs extension for the files
|
||||||
// Templates get registered with their relative name
|
// Templates get registered with their relative name
|
||||||
|
|
BIN
src/static/images/404.png
Normal file
BIN
src/static/images/404.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.9 KiB |
62
src/static/templates/404.hbs
Normal file
62
src/static/templates/404.hbs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||||
|
<meta name="robots" content="noindex,nofollow" />
|
||||||
|
<link rel="icon" type="image/png" href="{{urlpath}}/vw_static/vaultwarden-icon.png">
|
||||||
|
<title>Page not found!</title>
|
||||||
|
<link rel="stylesheet" href="{{urlpath}}/vw_static/bootstrap.css" />
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
padding-top: 75px;
|
||||||
|
}
|
||||||
|
.vaultwarden-icon {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
height: 32px;
|
||||||
|
width: auto;
|
||||||
|
margin: -5px 0 0 0;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
padding: 40px 0 40px 0;
|
||||||
|
border-top: 1px solid #dee2e6;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 980px;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
padding-top: 20px;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 15px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="bg-light">
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-md navbar-dark bg-dark mb-4 shadow fixed-top">
|
||||||
|
<div class="container">
|
||||||
|
<a class="navbar-brand" href="{{urlpath}}/"><img class="vaultwarden-icon" src="{{urlpath}}/vw_static/vaultwarden-icon.png" alt="V">aultwarden</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse"
|
||||||
|
aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarCollapse">
|
||||||
|
<ul class="navbar-nav me-auto">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main class="container inner content text-center">
|
||||||
|
<h2>Page not found!</h2>
|
||||||
|
<p class="lead">Sorry, but the page you were looking for could not be found.</p>
|
||||||
|
<p class="display-6">
|
||||||
|
<a href="{{urlpath}}/"><img style="max-width: 500px; width: 100%;" src="{{urlpath}}/vw_static/404.png" alt="Return to the web vault?"></a></p>
|
||||||
|
<p>You can <a href="{{urlpath}}/">return to the web-vault</a>, or <a href="https://github.com/dani-garcia/vaultwarden">contact us</a>.</p>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<div class="container footer text-muted content">Vaultwarden (unofficial Bitwarden® server)</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in a new issue