about summary refs log tree commit diff
path: root/src/indieauth.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/indieauth.rs')
-rw-r--r--src/indieauth.rs99
1 files changed, 71 insertions, 28 deletions
diff --git a/src/indieauth.rs b/src/indieauth.rs
index 27a70a1..f6bac04 100644
--- a/src/indieauth.rs
+++ b/src/indieauth.rs
@@ -1,11 +1,11 @@
 use async_trait::async_trait;
 #[allow(unused_imports)]
-use log::{error,info};
-use url::Url;
+use log::{error, info};
+use std::sync::Arc;
 use tide::prelude::*;
 #[allow(unused_imports)]
-use tide::{Request, Response, Next, Result};
-use std::sync::Arc;
+use tide::{Next, Request, Response, Result};
+use url::Url;
 
 use crate::database;
 use crate::ApplicationState;
@@ -14,7 +14,7 @@ use crate::ApplicationState;
 pub struct User {
     pub me: Url,
     pub client_id: Url,
-    scope: String
+    scope: String,
 }
 
 impl User {
@@ -28,23 +28,40 @@ impl User {
         Self {
             me: Url::parse(me).unwrap(),
             client_id: Url::parse(client_id).unwrap(),
-            scope: scope.to_string()
+            scope: scope.to_string(),
         }
     }
 }
 
 #[cfg(any(not(debug_assertions), test))]
-async fn get_token_data(token: String, token_endpoint: &http_types::Url, http_client: &surf::Client) -> (http_types::StatusCode, Option<User>) {
-    match http_client.get(token_endpoint).header("Authorization", token).header("Accept", "application/json").send().await {
+async fn get_token_data(
+    token: String,
+    token_endpoint: &http_types::Url,
+    http_client: &surf::Client,
+) -> (http_types::StatusCode, Option<User>) {
+    match http_client
+        .get(token_endpoint)
+        .header("Authorization", token)
+        .header("Accept", "application/json")
+        .send()
+        .await
+    {
         Ok(mut resp) => {
             if resp.status() == 200 {
                 match resp.body_json::<User>().await {
                     Ok(user) => {
-                        info!("Token endpoint request successful. Validated user: {}", user.me);
+                        info!(
+                            "Token endpoint request successful. Validated user: {}",
+                            user.me
+                        );
                         (resp.status(), Some(user))
-                    },
+                    }
                     Err(err) => {
-                        error!("Token endpoint parsing error (HTTP status {}): {}", resp.status(), err);
+                        error!(
+                            "Token endpoint parsing error (HTTP status {}): {}",
+                            resp.status(),
+                            err
+                        );
                         (http_types::StatusCode::InternalServerError, None)
                     }
                 }
@@ -63,7 +80,7 @@ async fn get_token_data(token: String, token_endpoint: &http_types::Url, http_cl
 pub struct IndieAuthMiddleware {
     #[allow(dead_code)] // it's not really dead since it's only dead in debug scope
     cache: Arc<retainer::Cache<String, User>>,
-    monitor_task: Option<async_std::task::JoinHandle<()>>
+    monitor_task: Option<async_std::task::JoinHandle<()>>,
 }
 impl IndieAuthMiddleware {
     /// Create a new instance of IndieAuthMiddleware.
@@ -74,12 +91,19 @@ impl IndieAuthMiddleware {
     pub fn new() -> Self {
         let cache: Arc<retainer::Cache<String, User>> = Arc::new(retainer::Cache::new());
         let cache_clone = cache.clone();
-        let task = async_std::task::spawn(async move { cache_clone.monitor(4, 0.1, std::time::Duration::from_secs(30)).await });
+        let task = async_std::task::spawn(async move {
+            cache_clone
+                .monitor(4, 0.1, std::time::Duration::from_secs(30))
+                .await
+        });
 
         #[cfg(all(debug_assertions, not(test)))]
         error!("ATTENTION: You are running in debug mode. NO REQUESTS TO TOKEN ENDPOINT WILL BE MADE. YOU WILL BE PROCEEDING WITH DEBUG USER CREDENTIALS. DO NOT RUN LIKE THIS IN PRODUCTION.");
 
-        Self { cache, monitor_task: Some(task) }
+        Self {
+            cache,
+            monitor_task: Some(task),
+        }
     }
 }
 impl Drop for IndieAuthMiddleware {
@@ -96,7 +120,8 @@ impl Drop for IndieAuthMiddleware {
         // (it is safe tho cuz None is no nullptr and dereferencing it doesn't cause unsafety)
         // (could cause a VERY FUNNY race condition to occur though
         //  if you tried to refer to the value in another thread!)
-        let task = std::mem::take(&mut self.monitor_task).expect("Dropped IndieAuthMiddleware TWICE? Impossible!");
+        let task = std::mem::take(&mut self.monitor_task)
+            .expect("Dropped IndieAuthMiddleware TWICE? Impossible!");
         // Then cancel the task, using another task to request cancellation.
         // Because apparently you can't run async code from Drop...
         // This should drop the last reference for the [`cache`],
@@ -105,27 +130,41 @@ impl Drop for IndieAuthMiddleware {
     }
 }
 #[async_trait]
-impl<B> tide::Middleware<ApplicationState<B>> for IndieAuthMiddleware where
-    B: database::Storage + Send + Sync + Clone
+impl<B> tide::Middleware<ApplicationState<B>> for IndieAuthMiddleware
+where
+    B: database::Storage + Send + Sync + Clone,
 {
-
     #[cfg(all(not(test), debug_assertions))]
-    async fn handle(&self, mut req: Request<ApplicationState<B>>, next: Next<'_, ApplicationState<B>>) -> Result {
-        req.set_ext(User::new("http://localhost:8080/", "https://curl.haxx.se/","create update delete undelete media"));
+    async fn handle(
+        &self,
+        mut req: Request<ApplicationState<B>>,
+        next: Next<'_, ApplicationState<B>>,
+    ) -> Result {
+        req.set_ext(User::new(
+            "http://localhost:8080/",
+            "https://curl.haxx.se/",
+            "create update delete undelete media",
+        ));
         Ok(next.run(req).await)
     }
     #[cfg(any(not(debug_assertions), test))]
-    async fn handle(&self, mut req: Request<ApplicationState<B>>, next: Next<'_, ApplicationState<B>>) -> Result {
+    async fn handle(
+        &self,
+        mut req: Request<ApplicationState<B>>,
+        next: Next<'_, ApplicationState<B>>,
+    ) -> Result {
         let header = req.header("Authorization");
         match header {
             None => {
                 // TODO: move that to the request handling functions
                 // or make a middleware that refuses to accept unauthenticated requests
-                Ok(Response::builder(401).body(json!({
-                    "error": "unauthorized",
-                    "error_description": "Please provide an access token."
-                })).build())
-            },
+                Ok(Response::builder(401)
+                    .body(json!({
+                        "error": "unauthorized",
+                        "error_description": "Please provide an access token."
+                    }))
+                    .build())
+            }
             Some(value) => {
                 let endpoint = &req.state().token_endpoint;
                 let http_client = &req.state().http_client;
@@ -177,9 +216,13 @@ mod tests {
     use super::*;
     #[test]
     fn user_scopes_are_checkable() {
-        let user = User::new("https://fireburn.ru/", "https://quill.p3k.io/", "create update media");
+        let user = User::new(
+            "https://fireburn.ru/",
+            "https://quill.p3k.io/",
+            "create update media",
+        );
 
         assert!(user.check_scope("create"));
         assert!(!user.check_scope("delete"));
     }
-}
\ No newline at end of file
+}