about summary refs log tree commit diff
path: root/src/frontend/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/mod.rs')
-rw-r--r--src/frontend/mod.rs45
1 files changed, 42 insertions, 3 deletions
diff --git a/src/frontend/mod.rs b/src/frontend/mod.rs
index aaaa2b2..891e944 100644
--- a/src/frontend/mod.rs
+++ b/src/frontend/mod.rs
@@ -1,4 +1,4 @@
-use serde::Deserialize;
+use serde::{Serialize, Deserialize};
 use tide::{Request, Response, Result, StatusCode, Next};
 use log::{info,error};
 use crate::ApplicationState;
@@ -11,6 +11,7 @@ mod templates {
     use http_types::StatusCode;
     use ellipse::Ellipse;
     use chrono;
+    use super::IndiewebEndpoints;
 
     /// Return a pretty location specifier from a geo: URI.
     fn decode_geo_uri(uri: &str) -> String {
@@ -30,7 +31,7 @@ mod templates {
     }
 
     markup::define! {
-        Template<'a>(title: &'a str, content: String) {
+        Template<'a>(title: &'a str, endpoints: IndiewebEndpoints, content: String) {
             @markup::doctype()
             html {
                 head {
@@ -38,6 +39,10 @@ mod templates {
                     link[rel="preconnect", href="https://fonts.gstatic.com"];
                     link[rel="stylesheet", href="/static/style.css"];
                     meta[name="viewport", content="initial-scale=1, width=device-width"];
+                    // TODO: link rel= for common IndieWeb APIs: webmention, microsub
+                    link[rel="micropub", href="/micropub"]; // Static, because it's built into the server itself
+                    link[rel="authorization_endpoint", href=&endpoints.authorization_endpoint];
+                    link[rel="token_endpoint", href=&endpoints.token_endpoint];
                 }
                 body {
                     nav#headerbar {
@@ -379,6 +384,14 @@ mod templates {
 
 use templates::{Template,ErrorPage,MainPage};
 
+#[derive(Clone, Serialize, Deserialize)]
+pub struct IndiewebEndpoints {
+    authorization_endpoint: String,
+    token_endpoint: String,
+    webmention: Option<String>,
+    microsub: Option<String>
+}
+
 #[derive(Deserialize)]
 struct QueryParams {
     after: Option<String>
@@ -437,9 +450,16 @@ async fn get_post_from_database<S: Storage>(db: &S, url: &str, after: Option<Str
     }
 }
 
+pub async fn coffee<S: Storage>(_: Request<ApplicationState<S>>) -> Result {
+    Err(FrontendError::with_code(StatusCode::ImATeapot, "Someone asked this website to brew them some coffee..."))?;
+    return Ok(Response::builder(500).build()) // unreachable
+}
+
 pub async fn mainpage<S: Storage>(req: Request<ApplicationState<S>>) -> Result {
     let backend = &req.state().storage;
     let query = req.query::<QueryParams>()?;
+    let authorization_endpoint = req.state().authorization_endpoint.to_string();
+    let token_endpoint = req.state().token_endpoint.to_string();
     let user: Option<String> = None;
 
     #[cfg(any(not(debug_assertions), test))]
@@ -470,6 +490,10 @@ pub async fn mainpage<S: Storage>(req: Request<ApplicationState<S>>) -> Result {
             .content_type("text/html; charset=utf-8")
             .body(Template {
                 title: &format!("{} - Main page", url.host().unwrap().to_string()),
+                endpoints: IndiewebEndpoints {
+                  authorization_endpoint, token_endpoint,
+                  webmention: None, microsub: None
+                },
                 content: MainPage {
                     feed: &feed?,
                     card: &card?
@@ -481,6 +505,8 @@ pub async fn mainpage<S: Storage>(req: Request<ApplicationState<S>>) -> Result {
 
 pub async fn render_post<S: Storage>(req: Request<ApplicationState<S>>) -> Result {
     let query = req.query::<QueryParams>()?;
+    let authorization_endpoint = req.state().authorization_endpoint.to_string();
+    let token_endpoint = req.state().token_endpoint.to_string();
     let user: Option<String> = None;
 
     #[cfg(any(not(debug_assertions), test))]
@@ -501,6 +527,10 @@ pub async fn render_post<S: Storage>(req: Request<ApplicationState<S>>) -> Resul
         .content_type("text/html; charset=utf-8")
         .body(Template {
             title: post["properties"]["name"][0].as_str().unwrap_or(&format!("Note at {}", url.host().unwrap().to_string())),
+            endpoints: IndiewebEndpoints {
+                authorization_endpoint, token_endpoint,
+                webmention: None, microsub: None
+            },
             content: template
         }.to_string()
     ).build())
@@ -513,6 +543,8 @@ impl<S> tide::Middleware<ApplicationState<S>> for ErrorHandlerMiddleware where
     S: crate::database::Storage
 {
     async fn handle(&self, request: Request<ApplicationState<S>>, next: Next<'_, ApplicationState<S>>) -> Result {
+        let authorization_endpoint = request.state().authorization_endpoint.to_string();
+        let token_endpoint = request.state().token_endpoint.to_string();
         let mut res = next.run(request).await;
         let mut code: Option<StatusCode> = None;
         if let Some(err) = res.downcast_error::<FrontendError>() {
@@ -527,7 +559,14 @@ impl<S> tide::Middleware<ApplicationState<S>> for ErrorHandlerMiddleware where
         if let Some(code) = code {
             res.set_status(code);
             res.set_content_type("text/html; charset=utf-8");
-            res.set_body(Template { title: "Error", content: ErrorPage { code }.to_string()}.to_string());
+            res.set_body(Template {
+                title: "Error",
+                endpoints: IndiewebEndpoints {
+                    authorization_endpoint, token_endpoint,
+                    webmention: None, microsub: None
+                },
+                content: ErrorPage { code }.to_string()
+            }.to_string());
         }
         Ok(res)
     }