diff --git a/Cargo.lock b/Cargo.lock index 865aaae..8ff72ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -193,6 +193,21 @@ dependencies = [ "syn", ] +[[package]] +name = "actix-web-httpauth" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dda62cf04bc3a9ad2ea8f314f721951cfdb4cdacec4e984d20e77c7bb170991" +dependencies = [ + "actix-utils", + "actix-web", + "base64", + "futures-core", + "futures-util", + "log", + "pin-project-lite", +] + [[package]] name = "adler" version = "1.0.2" @@ -738,6 +753,7 @@ dependencies = [ "actix-rt", "actix-web", "actix-web-codegen-const-routes", + "actix-web-httpauth", "argon2-creds", "base64", "clap", diff --git a/Cargo.toml b/Cargo.toml index 6703565..1778f0e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ build = "build.rs" [dependencies] actix-web = "4" +actix-web-httpauth = "0.8.0" futures-util = { version = "0.3.17", default-features = false, features = ["std"] } lazy_static = "1.4.0" log = "0.4.17" diff --git a/src/api/v1/forms.rs b/src/api/v1/forms.rs index 5685d32..108869c 100644 --- a/src/api/v1/forms.rs +++ b/src/api/v1/forms.rs @@ -17,6 +17,7 @@ use std::collections::HashMap; use actix_web::{web, HttpResponse, Responder}; +use actix_web_httpauth::middleware::HttpAuthentication; use serde::{Deserialize, Serialize}; use crate::db::FormSubmission; @@ -24,6 +25,8 @@ use crate::errors::*; use crate::AppCtx; use crate::*; +use super::bearerauth; + pub mod routes { use super::*; #[derive(Debug, Eq, PartialEq, Deserialize, Serialize)] @@ -95,7 +98,10 @@ impl From for FormSubmissionResp { } } -#[actix_web_codegen_const_routes::post(path = "API_V1_ROUTES.forms.get_all")] +#[actix_web_codegen_const_routes::post( + path = "API_V1_ROUTES.forms.get_all", + wrap = "HttpAuthentication::bearer(bearerauth)" +)] async fn list_all( ctx: AppCtx, payload: web::Json, @@ -175,6 +181,8 @@ pub mod tests { let upload_path = API_V1_ROUTES.forms.get_submit(host, path); println!("{upload_path}"); + let _ = ctx.db.delete_site(host).await; + let foo = Foo { foo: "Foo".into(), num: 2.33, @@ -226,6 +234,10 @@ pub mod tests { test::TestRequest::post() .set_json(&payload) .uri(&get_sub_route) + .insert_header(( + header::AUTHORIZATION, + format!("Bearer {}", ctx.settings.dash.api_key), + )) .to_request(), ) .await; diff --git a/src/api/v1/mod.rs b/src/api/v1/mod.rs index c01a405..069c3e4 100644 --- a/src/api/v1/mod.rs +++ b/src/api/v1/mod.rs @@ -14,16 +14,17 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ +use crate::errors::ServiceError; +use crate::AppCtx; use actix_web::web; +use actix_web::{dev::ServiceRequest, Error}; +use actix_web_httpauth::extractors::bearer::BearerAuth; pub mod forms; pub mod meta; pub const API_V1_ROUTES: routes::Routes = routes::Routes::new(); -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct SignedInUser(String); - pub fn services(cfg: &mut web::ServiceConfig) { meta::services(cfg); forms::services(cfg); @@ -47,3 +48,17 @@ pub mod routes { } } } + +pub async fn bearerauth( + req: ServiceRequest, + credentials: BearerAuth, +) -> Result { + let ctx: &AppCtx = req.app_data().unwrap(); + let creds = credentials.token(); + if ctx.settings.dash.api_key == creds { + Ok(req) + } else { + let e = Error::from(ServiceError::Unauthorized); + Err((e, req)) + } +}