templating with Tera, copy templates to /var/lib/bespoke/templates in nix-built pkg

This commit is contained in:
Viv Lim 2022-10-03 02:32:41 -07:00
parent d34d93c507
commit 05a3e337a6
9 changed files with 410 additions and 9 deletions

45
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,45 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug executable 'bespoke'",
"cargo": {
"args": [
"build",
"--bin=bespoke",
"--package=bespoke"
],
"filter": {
"name": "bespoke",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in executable 'bespoke'",
"cargo": {
"args": [
"test",
"--no-run",
"--bin=bespoke",
"--package=bespoke"
],
"filter": {
"name": "bespoke",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
}
]
}

280
Cargo.lock generated
View File

@ -13,6 +13,15 @@ dependencies = [
"version_check",
]
[[package]]
name = "aho-corasick"
version = "0.7.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
dependencies = [
"memchr",
]
[[package]]
name = "android_system_properties"
version = "0.1.5"
@ -154,6 +163,7 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
name = "bespoke"
version = "0.1.0"
dependencies = [
"anyhow",
"async-session",
"async-trait",
"axum",
@ -164,6 +174,7 @@ dependencies = [
"reqwest",
"serde",
"serde_json",
"tera",
"tokio",
"tracing",
"tracing-subscriber",
@ -217,6 +228,15 @@ dependencies = [
"generic-array",
]
[[package]]
name = "bstr"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
dependencies = [
"memchr",
]
[[package]]
name = "bumpalo"
version = "3.11.0"
@ -260,6 +280,28 @@ dependencies = [
"winapi",
]
[[package]]
name = "chrono-tz"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29c39203181991a7dd4343b8005bd804e7a9a37afb8ac070e43771e8c820bbde"
dependencies = [
"chrono",
"chrono-tz-build",
"phf",
]
[[package]]
name = "chrono-tz-build"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f509c3a87b33437b05e2458750a0700e5bdd6956176773e6c7d6dd15a283a0c"
dependencies = [
"parse-zoneinfo",
"phf",
"phf_codegen",
]
[[package]]
name = "config"
version = "0.13.2"
@ -300,6 +342,15 @@ dependencies = [
"libc",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
@ -330,6 +381,12 @@ dependencies = [
"subtle",
]
[[package]]
name = "deunicode"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "850878694b7933ca4c9569d30a34b55031b9b139ee1fc7b94a527c4ef960d690"
[[package]]
name = "digest"
version = "0.9.0"
@ -456,6 +513,30 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "globset"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a"
dependencies = [
"aho-corasick",
"bstr",
"fnv",
"log",
"regex",
]
[[package]]
name = "globwalk"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc"
dependencies = [
"bitflags",
"ignore",
"walkdir",
]
[[package]]
name = "h2"
version = "0.3.14"
@ -568,6 +649,12 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
[[package]]
name = "humansize"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026"
[[package]]
name = "hyper"
version = "0.14.20"
@ -628,6 +715,24 @@ dependencies = [
"unicode-normalization",
]
[[package]]
name = "ignore"
version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d"
dependencies = [
"crossbeam-utils",
"globset",
"lazy_static",
"log",
"memchr",
"regex",
"same-file",
"thread_local",
"walkdir",
"winapi-util",
]
[[package]]
name = "indexmap"
version = "1.9.1"
@ -856,6 +961,15 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "parse-zoneinfo"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41"
dependencies = [
"regex",
]
[[package]]
name = "pathdiff"
version = "0.2.1"
@ -912,6 +1026,45 @@ dependencies = [
"sha1",
]
[[package]]
name = "phf"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c"
dependencies = [
"phf_shared",
]
[[package]]
name = "phf_codegen"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a56ac890c5e3ca598bbdeaa99964edb5b0258a583a9eb6ef4e89fc85d9224770"
dependencies = [
"phf_generator",
"phf_shared",
]
[[package]]
name = "phf_generator"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf"
dependencies = [
"phf_shared",
"rand",
]
[[package]]
name = "phf_shared"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676"
dependencies = [
"siphasher",
"uncased",
]
[[package]]
name = "pin-project"
version = "1.0.12"
@ -1013,6 +1166,8 @@ version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
@ -1133,6 +1288,15 @@ version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
@ -1254,6 +1418,12 @@ dependencies = [
"libc",
]
[[package]]
name = "siphasher"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
[[package]]
name = "slab"
version = "0.4.7"
@ -1263,6 +1433,15 @@ dependencies = [
"autocfg",
]
[[package]]
name = "slug"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3bc762e6a4b6c6fcaade73e77f9ebc6991b676f88bb2358bddb56560f073373"
dependencies = [
"deunicode",
]
[[package]]
name = "smallvec"
version = "1.9.0"
@ -1308,6 +1487,28 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8"
[[package]]
name = "tera"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3df578c295f9ec044ff1c829daf31bb7581d5b3c2a7a3d87419afe1f2531438c"
dependencies = [
"chrono",
"chrono-tz",
"globwalk",
"humansize",
"lazy_static",
"percent-encoding",
"pest",
"pest_derive",
"rand",
"regex",
"serde",
"serde_json",
"slug",
"unic-segment",
]
[[package]]
name = "thiserror"
version = "1.0.37"
@ -1545,6 +1746,65 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81"
[[package]]
name = "uncased"
version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09b01702b0fd0b3fadcf98e098780badda8742d4f4a7676615cad90e8ac73622"
dependencies = [
"version_check",
]
[[package]]
name = "unic-char-property"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221"
dependencies = [
"unic-char-range",
]
[[package]]
name = "unic-char-range"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc"
[[package]]
name = "unic-common"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc"
[[package]]
name = "unic-segment"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23"
dependencies = [
"unic-ucd-segment",
]
[[package]]
name = "unic-ucd-segment"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700"
dependencies = [
"unic-char-property",
"unic-char-range",
"unic-ucd-version",
]
[[package]]
name = "unic-ucd-version"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4"
dependencies = [
"unic-common",
]
[[package]]
name = "unicode-bidi"
version = "0.3.8"
@ -1596,6 +1856,17 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "walkdir"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
dependencies = [
"same-file",
"winapi",
"winapi-util",
]
[[package]]
name = "want"
version = "0.3.0"
@ -1723,6 +1994,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"

View File

@ -20,4 +20,6 @@ async-session = "3.0.0"
reqwest = { version = "0.11", default-features = false, features = ["json"] }
headers = "0.3"
async-trait = "0.1.57"
http = "0.2"
http = "0.2"
tera = "1.17"
anyhow = "*"

View File

@ -53,6 +53,13 @@ naersk.lib."${targetPlatform.system}".buildPackage rec {
license = with licenses; [ mit ];
maintainers = with maintainers; [ ];
};
postInstall = ''
mkdir -p "$out/var/lib/bespoke/templates"
ls .
pwd
cp ./templates/* "$out/var/lib/bespoke/templates"
'';
}

View File

@ -17,11 +17,17 @@ use oauth2::{
use serde::{Deserialize, Serialize};
use std::{net::SocketAddr, collections::HashSet, sync::Arc};
use tokio::sync::Mutex;
use tera::{Tera, Context};
use crate::templating::TeraWrapper;
pub mod templating;
static COOKIE_NAME: &str = "SESSION";
#[derive(Debug, Deserialize, Clone)]
struct Settings {
listen_addr: String,
client_id: String,
client_secret: String,
redirect_url: String,
@ -79,6 +85,8 @@ async fn main() {
.try_deserialize()
.unwrap();
let tera = TeraWrapper::new("templates/*", "error.html").expect("couldn't load templates");
let auth_state = AuthState::new(settings.oauth_client());
// use something persistent in prod, if it matters
let session_store = MemoryStore::new();
@ -90,13 +98,14 @@ async fn main() {
.route("/auth/authorized", get(login_authorized))
.route("/protected", get(protected))
.route("/logout", get(logout))
.layer(Extension(settings))
.layer(Extension(settings.clone()))
.layer(Extension(auth_state))
.layer(Extension(session_store));
.layer(Extension(session_store))
.layer(Extension(tera));
// run our app with hyper
// `axum::Server` is a re-export of `hyper::Server`
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
let addr: SocketAddr = settings.listen_addr.parse().expect("Cannot parse listen address");
tracing::debug!("listening on {}", addr);
axum::Server::bind(&addr)
.serve(app.into_make_service())
@ -105,11 +114,14 @@ async fn main() {
}
// basic handler that responds with a static string
async fn root(user: Option<User>) -> impl IntoResponse {
match user {
Some(u) => format!("Hello {}", u.name),
None => "hello world. <a href=\"/login\">login</a>".to_string()
}
async fn root(Extension(tera): Extension<TeraWrapper>, user: Option<User>) -> impl IntoResponse {
let mut context = Context::new();
context.try_insert("is_authenticated", match user {
Some(_) => &true,
None => &false
}).unwrap();
context.try_insert("user", &user).unwrap();
tera.build_response("index.html", &context)
}
#[derive(Debug, Serialize, Deserialize)]
struct User {

41
src/templating/mod.rs Normal file
View File

@ -0,0 +1,41 @@
use axum::response::{IntoResponse, Response};
use http::StatusCode;
use tera::{Tera, Context};
#[derive(Clone)]
pub struct TeraWrapper {
tera: Tera,
error_template_name: String
}
impl TeraWrapper {
pub fn new(dir: &str, error_template_name: &str) -> anyhow::Result<Self> {
Ok(Self {
tera: Tera::new(dir)?,
error_template_name: error_template_name.to_string()
})
}
pub fn build_response(&self, template_name: &str, context: &Context) -> Response {
match self.try_render_context(template_name, context) {
Ok(document) => axum::response::Html::from(document).into_response(),
Err(e) => {
// Try to render the error template.
let mut error_context = Context::new();
error_context.insert("error_debug_repr", &format!("{:?}", e));
match self.try_render_context(&self.error_template_name, &error_context) {
Ok(error_document) => axum::response::Html::from(error_document).into_response(),
Err(e_inner) => {
(StatusCode::INTERNAL_SERVER_ERROR, format!("Page failed with error {:?}, and rendering error template failed with {:?}", e, e_inner)).into_response()
},
}
}
}
}
fn try_render_context(&self, template_name: &str, context: &Context) -> anyhow::Result<String> {
Ok(self.tera.render(template_name, context)?)
}
}

2
templates/error.html Normal file
View File

@ -0,0 +1,2 @@
<h1>oh no!</h1>
<pre>{{error_debug_repr}}</pre>

9
templates/header.html Normal file
View File

@ -0,0 +1,9 @@
<h1>bespoke</h1>
<p>
{% if is_authenticated %}
logged in as {{user.name}}. <a href="/logout">log out</a>
{% else %}
<a href="/login">log in</a>
{% endif %}
</p>
<hr />

3
templates/index.html Normal file
View File

@ -0,0 +1,3 @@
{% include "header.html" %}
greetz