refactor(server): create auth handler module

This commit is contained in:
orhun 2021-07-24 14:38:53 +03:00
parent 181c8c602c
commit 12c204bf03
No known key found for this signature in database
GPG key ID: F83424824B3E4B90
3 changed files with 51 additions and 18 deletions

44
src/auth.rs Normal file
View file

@ -0,0 +1,44 @@
use actix_web::http::header::AUTHORIZATION;
use actix_web::http::HeaderMap;
use actix_web::{error, Error};
/// Checks the authorization header for the specified token.
///
/// `Authorization: (type) <token>`
pub fn check(host: &str, headers: &HeaderMap, token: Option<String>) -> Result<(), Error> {
if let Some(token) = token {
if !token.is_empty() {
let auth_header = headers
.get(AUTHORIZATION)
.map(|v| v.to_str().unwrap_or_default())
.map(|v| v.split_whitespace().last().unwrap_or_default());
if auth_header.unwrap_or_default() != token {
log::warn!(
"authorization failure for {} (header: {})",
host,
auth_header.unwrap_or("none"),
);
return Err(error::ErrorUnauthorized("unauthorized"));
}
}
}
Ok(())
}
#[cfg(test)]
mod test {
use super::*;
use actix_web::http::HeaderValue;
#[test]
fn test_check_auth() -> Result<(), Error> {
let mut headers = HeaderMap::new();
headers.insert(AUTHORIZATION, HeaderValue::from_static("basic test_token"));
assert!(check("", &headers, Some(String::from("test_token"))).is_ok());
assert!(check("", &headers, Some(String::from("invalid_token"))).is_err());
assert!(check("", &headers, None).is_ok());
assert!(check("", &HeaderMap::new(), None).is_ok());
assert!(check("", &HeaderMap::new(), Some(String::from("token"))).is_err());
Ok(())
}
}

View file

@ -7,8 +7,11 @@ pub mod config;
/// Server routes. /// Server routes.
pub mod server; pub mod server;
/// HTTP headers.
pub mod header;
/// File handler. /// File handler.
pub mod file; pub mod file;
/// HTTP headers. /// Auth handler.
pub mod header; pub mod auth;

View file

@ -1,9 +1,9 @@
use crate::auth;
use crate::config::Config; use crate::config::Config;
use crate::file; use crate::file;
use crate::header::ContentDisposition; use crate::header::ContentDisposition;
use actix_files::NamedFile; use actix_files::NamedFile;
use actix_multipart::Multipart; use actix_multipart::Multipart;
use actix_web::http::header::AUTHORIZATION;
use actix_web::{error, get, post, web, Error, HttpRequest, HttpResponse, Responder}; use actix_web::{error, get, post, web, Error, HttpRequest, HttpResponse, Responder};
use byte_unit::Byte; use byte_unit::Byte;
use futures_util::stream::StreamExt; use futures_util::stream::StreamExt;
@ -40,21 +40,7 @@ async fn upload(
) -> Result<HttpResponse, Error> { ) -> Result<HttpResponse, Error> {
let connection = request.connection_info(); let connection = request.connection_info();
let host = connection.remote_addr().unwrap_or("unknown host"); let host = connection.remote_addr().unwrap_or("unknown host");
if let Ok(token) = env::var("AUTH_TOKEN") { auth::check(host, request.headers(), env::var("AUTH_TOKEN").ok())?;
let auth_header = request
.headers()
.get(AUTHORIZATION)
.map(|v| v.to_str().unwrap_or_default())
.map(|v| v.split_whitespace().last().unwrap_or_default());
if auth_header.unwrap_or_default() != token {
log::warn!(
"authorization failure for {} (header: {})",
host,
auth_header.unwrap_or("none"),
);
return Err(error::ErrorUnauthorized("unauthorized"));
}
}
let mut urls: Vec<String> = Vec::new(); let mut urls: Vec<String> = Vec::new();
while let Some(item) = payload.next().await { while let Some(item) = payload.next().await {
let mut field = item?; let mut field = item?;